diff options
Diffstat (limited to 'erts/emulator/test')
219 files changed, 79147 insertions, 0 deletions
diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile new file mode 100644 index 0000000000..b1374950b2 --- /dev/null +++ b/erts/emulator/test/Makefile @@ -0,0 +1,194 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1997-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include $(ERL_TOP)/make/target.mk + +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +EBIN = . + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +MODULES= \ + a_SUITE \ + after_SUITE \ + alloc_SUITE \ + beam_SUITE \ + beam_literals_SUITE \ + bif_SUITE \ + big_SUITE \ + binary_SUITE \ + bs_bincomp_SUITE \ + bs_bit_binaries_SUITE \ + bs_construct_SUITE \ + bs_match_bin_SUITE \ + bs_match_int_SUITE \ + bs_match_tail_SUITE \ + bs_match_misc_SUITE \ + bs_utf_SUITE \ + busy_port_SUITE \ + call_trace_SUITE \ + code_SUITE \ + crypto_SUITE \ + ddll_SUITE \ + decode_packet_SUITE \ + distribution_SUITE \ + driver_SUITE \ + efile_SUITE \ + erts_debug_SUITE \ + estone_SUITE \ + erl_link_SUITE \ + erl_drv_thread_SUITE \ + evil_SUITE \ + exception_SUITE \ + float_SUITE \ + fun_SUITE \ + fun_r11_SUITE \ + gc_SUITE \ + guard_SUITE \ + hash_SUITE \ + hibernate_SUITE \ + list_bif_SUITE \ + match_spec_SUITE \ + module_info_SUITE \ + monitor_SUITE \ + nested_SUITE \ + nif_SUITE \ + node_container_SUITE \ + nofrag_SUITE \ + num_bif_SUITE \ + obsolete_SUITE \ + op_SUITE \ + port_SUITE \ + port_bif_SUITE \ + process_SUITE \ + pseudoknot_SUITE \ + ref_SUITE \ + register_SUITE \ + save_calls_SUITE \ + send_term_SUITE \ + sensitive_SUITE \ + signal_SUITE \ + statistics_SUITE \ + system_info_SUITE \ + system_profile_SUITE \ + time_SUITE \ + timer_bif_SUITE \ + trace_SUITE \ + trace_bif_SUITE \ + trace_nif_SUITE \ + trace_port_SUITE \ + tuple_SUITE \ + trace_local_SUITE \ + trace_meta_SUITE \ + trace_call_count_SUITE \ + scheduler_SUITE \ + old_scheduler_SUITE \ + z_SUITE \ + old_mod \ + long_timers_test \ + ignore_cores \ + dgawd_handler \ + random_iolist \ + crypto_reference + +NO_OPT= bs_bincomp \ + bs_bit_binaries \ + bs_construct \ + bs_match_bin \ + bs_match_int \ + bs_match_tail \ + bs_match_misc \ + bs_utf + + +NO_OPT_MODULES= $(NO_OPT:%=%_no_opt_SUITE) +NO_OPT_ERL_FILES= $(NO_OPT_MODULES:%=%.erl) + +ERL_FILES= $(MODULES:%=%.erl) + +TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR)) + +EMAKEFILE=Emakefile + +TEST_SPEC_FILES = emulator.spec \ + emulator.spec.win \ + emulator.spec.vxworks \ + emulator.spec.ose +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/emulator_test + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- +ERL_MAKE_FLAGS += +ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +make_emakefile: $(NO_OPT_ERL_FILES) + # This special rule can be removed when communication with R7B nodes + # is no longer supported. + $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) +compressed -o$(EBIN) \ + '*_SUITE_make' > $(EMAKEFILE) + $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) +compressed -o$(EBIN) \ + $(MODULES) >> $(EMAKEFILE) + $(ERL_TOP)/make/make_emakefile +no_copt +no_postopt $(ERL_COMPILE_FLAGS) \ + -o$(EBIN) $(NO_OPT_MODULES) >> $(EMAKEFILE) + +tests debug opt: make_emakefile + erl $(ERL_MAKE_FLAGS) -make + +clean: + rm -f $(EMAKEFILE) + rm -f $(TARGET_FILES) + rm -f core *~ + +docs: + +# ---------------------------------------------------- +# Special targets +# ---------------------------------------------------- + +%_no_opt_SUITE.erl: %_SUITE.erl + sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@ + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: + +release_tests_spec: make_emakefile + $(INSTALL_DIR) $(RELSYSDIR) + $(INSTALL_DATA) $(EMAKEFILE) $(TEST_SPEC_FILES) \ + $(ERL_FILES) $(RELSYSDIR) + $(INSTALL_DATA) $(NO_OPT_ERL_FILES) $(RELSYSDIR) + chmod -f -R u+w $(RELSYSDIR) + tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) + +release_docs_spec: + diff --git a/erts/emulator/test/a_SUITE.erl b/erts/emulator/test/a_SUITE.erl new file mode 100644 index 0000000000..e9d653a7c4 --- /dev/null +++ b/erts/emulator/test/a_SUITE.erl @@ -0,0 +1,99 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%%------------------------------------------------------------------- +%%% File : a_SUITE.erl +%%% Author : Rickard Green <[email protected]> +%%% Description : Misc tests that should be run first +%%% +%%% Created : 21 Aug 2006 by Rickard Green <[email protected]> +%%%------------------------------------------------------------------- +-module(a_SUITE). + +-include("test_server.hrl"). + +-export([all/1, long_timers/1, pollset_size/1]). + +all(doc) -> + []; +all(suite) -> + [long_timers, pollset_size]. + +long_timers(doc) -> + []; +long_timers(suite) -> + []; +long_timers(Config) when is_list(Config) -> + Dir = ?config(data_dir, Config), + ?line long_timers_test:start(Dir), + ?line {comment, + "Testcase started! This test will run in parallel with the " + "erts testsuite and ends in the z_SUITE:long_timers testcase."}. + +pollset_size(doc) -> + []; +pollset_size(suite) -> + []; +pollset_size(Config) when is_list(Config) -> + ?line Parent = self(), + ?line Go = make_ref(), + ?line spawn(fun () -> + Name = pollset_size_testcase_initial_state_holder, + true = register(Name, self()), + ChkIo = get_check_io_info(), + io:format("Initial: ~p~n", [ChkIo]), + Parent ! Go, + receive + {get_initial_check_io_result, Pid} -> + Pid ! {initial_check_io_result, ChkIo} + end + end), + ?line receive Go -> ok end, + ?line {comment, + "Testcase started! This test will run in parallel with the " + "erts testsuite and ends in the z_SUITE:pollset_size testcase."}. + +%% +%% Internal functions... +%% + +display_check_io(ChkIo) -> + catch erlang:display('--- CHECK IO INFO ---'), + catch erlang:display(ChkIo), + catch erts_debug:set_internal_state(available_internal_state, true), + NoOfErrorFds = (catch erts_debug:get_internal_state(check_io_debug)), + catch erlang:display({'NoOfErrorFds', NoOfErrorFds}), + catch erts_debug:set_internal_state(available_internal_state, false), + catch erlang:display('--- CHECK IO INFO ---'), + ok. + +get_check_io_info() -> + ChkIo = erlang:system_info(check_io), + case lists:keysearch(pending_updates, 1, ChkIo) of + {value, {pending_updates, 0}} -> + display_check_io(ChkIo), + ChkIo; + false -> + ChkIo; + _ -> + receive after 10 -> ok end, + get_check_io_info() + end. + + diff --git a/erts/emulator/test/a_SUITE_data/Makefile.src b/erts/emulator/test/a_SUITE_data/Makefile.src new file mode 100644 index 0000000000..b4f1c4a2a5 --- /dev/null +++ b/erts/emulator/test/a_SUITE_data/Makefile.src @@ -0,0 +1,10 @@ +# +# NOTE: +# Suites with makefiles are run first. We want a_SUITE to be run first; +# therefore, keep this makefile even if it should be empty. +# + +all: timer_driver@dll@ + +@SHLIB_RULES@ + diff --git a/erts/emulator/test/a_SUITE_data/timer_driver.c b/erts/emulator/test/a_SUITE_data/timer_driver.c new file mode 100644 index 0000000000..ef4dcdf501 --- /dev/null +++ b/erts/emulator/test/a_SUITE_data/timer_driver.c @@ -0,0 +1,77 @@ +/* + * Copied from driver_SUITE and modified... + */ + +#include <stdio.h> +#include "erl_driver.h" + +#define get_int32(s) ((((unsigned char*) (s))[0] << 24) | \ + (((unsigned char*) (s))[1] << 16) | \ + (((unsigned char*) (s))[2] << 8) | \ + (((unsigned char*) (s))[3])) + +#define START_TIMER 0 +#define CANCEL_TIMER 1 +#define DELAY_START_TIMER 2 +#define TIMER 3 +#define CANCELLED 4 + +static ErlDrvData timer_start(ErlDrvPort, char*); +static void timer_stop(ErlDrvData), timer_read(ErlDrvData, char*, int), timer(ErlDrvData); + +static ErlDrvEntry timer_driver_entry = +{ + NULL, + timer_start, + timer_stop, + timer_read, + NULL, + NULL, + "timer_driver", + NULL, + NULL, + NULL, + timer, + NULL, + NULL +}; + +DRIVER_INIT(timer_drv) +{ + return &timer_driver_entry; +} + +static ErlDrvData timer_start(ErlDrvPort port, char *buf) +{ + return (ErlDrvData)port; +} + +/* set the timer, this is monitored from erlang measuring the time */ +static void timer_read(ErlDrvData port, char *buf, int len) +{ + char reply[1]; + + if (buf[0] == START_TIMER) { + /* fprintf(stderr, "[timer_drv] Setting timeout: %i\n", get_int32(buf + 1)); */ + driver_set_timer(port, get_int32(buf + 1)); + } else if (buf[0] == CANCEL_TIMER) { + /* fprintf(stderr, "[timer_drv] Timer cancelled\n"); */ + driver_cancel_timer(port); + reply[0] = CANCELLED; + driver_output(port, reply, 1); + } +} + +static void timer_stop(ErlDrvData port) +{ + driver_cancel_timer(port); +} + +static void timer(ErlDrvData port) +{ + char reply[1]; + + /* fprintf(stderr, "[timer_drv] timer timed out\n"); */ + reply[0] = TIMER; + driver_output((ErlDrvPort)port, reply, 1); +} diff --git a/erts/emulator/test/after_SUITE.erl b/erts/emulator/test/after_SUITE.erl new file mode 100644 index 0000000000..3e1a871408 --- /dev/null +++ b/erts/emulator/test/after_SUITE.erl @@ -0,0 +1,233 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(after_SUITE). + +%% Tests receive after. + +-include("test_server.hrl"). + +-export([all/1, t_after/1, receive_after/1, receive_after_big/1, + receive_after_errors/1, receive_var_zero/1, receive_zero/1, + multi_timeout/1, receive_after_32bit/1]). + +-export([init_per_testcase/2, fin_per_testcase/2]). + +%% Internal exports. + +-export([timeout_g/0]). + +all(suite) -> + [t_after, receive_after, receive_after_big, receive_after_errors, + receive_var_zero, receive_zero, multi_timeout, receive_after_32bit]. + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog=?t:timetrap(?t:minutes(3)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +%% Tests for an old round-off error in 'receive after'." +t_after(Config) when is_list(Config) -> + ?line spawn(fun frequent_process/0), + ?line Period = test_server:minutes(1), + ?line Before = erlang:now(), + receive + after Period -> + ?line After = erlang:now(), + ?line report(Period, Before, After) + end. + + +report(Period, Before, After) -> + ?line Elapsed = (element(1, After)*1000000000 + +element(2, After)*1000 + +element(3, After) div 1000) - + (element(1,Before)*1000000000 + + element(2,Before)*1000 + element(3,Before) div 1000), + ?line case Elapsed*100 / Period of + Percent when Percent > 100.10 -> + ?line test_server:fail({too_inaccurate, Percent}); + Percent when Percent < 100.0 -> + ?line test_server:fail({too_early, Percent}); + Percent -> + ?line Comment = io_lib:format("Elapsed/expected: ~.2f %", + [Percent]), + {comment, lists:flatten(Comment)} + end. + +frequent_process() -> + receive + after 100 -> + ?line frequent_process() + end. + +receive_after(doc) -> + "Test that 'receive after' works (doesn't hang). " + "The test takes 10 seconds to complete."; +receive_after(Config) when is_list(Config) -> + ?line receive_after1(5000). + +receive_after1(1) -> + ?line io:format("Testing: receive after ~p~n", [1]), + ?line receive after 1 -> ok end; +receive_after1(N) -> + ?line io:format("Testing: receive after ~p~n", [N]), + ?line receive after N -> receive_after1(N div 2) end. + +receive_after_big(Config) when is_list(Config) -> + %% Test that 'receive after' with a 32 bit number works. + receive_after_big1(16#f7654321), + receive_after_big2(). + +receive_after_big1(Timeout) -> + Self = self(), + erlang:yield(), + spawn(fun() -> Self ! here_is_a_message end), + ok = receive + here_is_a_message -> + ok + after Timeout -> + %% We test that the timeout can be set, + %% not that an timeout occurs after the appropriate delay + %% (48 days, 56 minutes, 48 seconds)! + timeout + end. + +receive_after_big2() -> + Self = self(), + erlang:yield(), + spawn(fun() -> Self ! here_is_a_message end), + ok = receive + here_is_a_message -> + ok + after 16#f7999977 -> + %% We only test that the timeout can be set. + timeout + end. + +-define(TryAfter(Timeout), + {'EXIT',{timeout_value,_}} = (catch receive mission -> exit(impossible) after Timeout -> ok end), + {'EXIT',{timeout_value,_}} = (catch receive after Timeout -> ok end), + try_after(Timeout)). + +%% Test error cases for 'receive after'. +receive_after_errors(Config) when is_list(Config) -> + ?line ?TryAfter(-1), + ?line ?TryAfter(0.0), + ?line ?TryAfter(3.14), + ?line ?TryAfter(16#100000000), + ?line ?TryAfter(392347129847294724972398472984729847129874), + ?line ?TryAfter(16#3fffffffffffffff), + ?line ?TryAfter(16#ffffffffffffffff), + ?line ?TryAfter(-16#100000000), + ?line ?TryAfter(-3891278094774921784123987129848), + ?line ?TryAfter(xxx), + ok. + +try_after(Timeout) -> + {'EXIT',{timeout_value,_}} = (catch receive after Timeout -> ok end). + +receive_var_zero(doc) -> "Test 'after Z', when Z == 0."; +receive_var_zero(Config) when is_list(Config) -> + self() ! x, + self() ! y, + Z = zero(), + timeout = receive + z -> ok + after Z -> timeout + end, + timeout = receive + after Z -> timeout + end, + self() ! w, + receive + x -> ok; + Other -> + ?line ?t:fail({bad_message,Other}) + end. + +zero() -> 0. + +%% Test 'after 0'. +receive_zero(Config) when is_list(Config) -> + self() ! x, + self() ! y, + timeout = receive + z -> ok + after 0 -> + timeout + end, + self() ! w, + timeout = receive + after 0 -> timeout + end, + receive + x -> ok; + Other -> + ?line ?t:fail({bad_message,Other}) + end. + +multi_timeout(doc) -> + "Test for catching invalid assertion in erl_message.c (in queue_message)." + "This failed (dumped core) with debug-compiled emulator."; +multi_timeout(Config) when is_list(Config) -> + ?line P = spawn(?MODULE, timeout_g, []), + ?line P ! a, + ?line P ! b, + ?line receive + after 1000 -> ok + end, + ?line P ! c, + ?line receive + after 1000 -> ok + end, + ?line P ! d, + ok. + +timeout_g() -> + ?line receive + a -> ok + end, + ?line receive + after 100000 -> ok + end, + ok. + +%% OTP-7493: Timeout for 32 bit numbers (such as 16#ffffFFFF) could +%% timeout at once. +receive_after_32bit(Config) when is_list(Config) -> + T = 16#ffffFFFF, + Pids = [spawn_link(fun() -> recv_after_32bit(I, T) end) || + I <- lists:seq(1, 2048)], + + %% Wait two seconds for any of the processes to timeout too early. + receive after 2000 -> ok end, + + %% Kill the processes. + [begin unlink(Pid), exit(Pid, kill) end || Pid <- Pids], + ok. + +recv_after_32bit(I, T) when I rem 2 =:= 0 -> + receive after T -> exit(timeout) end; +recv_after_32bit(_, _) -> + receive after 16#ffffFFFF -> exit(timeout) end. + diff --git a/erts/emulator/test/alloc_SUITE.erl b/erts/emulator/test/alloc_SUITE.erl new file mode 100644 index 0000000000..94766dc6e9 --- /dev/null +++ b/erts/emulator/test/alloc_SUITE.erl @@ -0,0 +1,179 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(alloc_SUITE). +-author('[email protected]'). +-export([all/1]). + +-export([basic/1, + coalesce/1, + threads/1, + realloc_copy/1, + bucket_index/1, + bucket_mask/1, + rbtree/1, + mseg_clear_cache/1]). + +-export([init_per_testcase/2, fin_per_testcase/2]). + +-include("test_server.hrl"). + +-define(DEFAULT_TIMETRAP_SECS, 240). + +all(doc) -> []; +all(suite) -> [basic, + coalesce, + threads, + realloc_copy, + bucket_index, + bucket_mask, + rbtree, + mseg_clear_cache]. + + +init_per_testcase(Case, Config) when is_list(Config) -> + Dog = ?t:timetrap(?t:seconds(?DEFAULT_TIMETRAP_SECS)), + [{watchdog, Dog},{testcase, Case}|Config]. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %% +%% Testcases %% +%% %% + +basic(suite) -> []; +basic(doc) -> []; +basic(Cfg) -> ?line drv_case(Cfg). + +coalesce(suite) -> []; +coalesce(doc) -> []; +coalesce(Cfg) -> ?line drv_case(Cfg). + +threads(suite) -> []; +threads(doc) -> []; +threads(Cfg) -> ?line drv_case(Cfg). + +realloc_copy(suite) -> []; +realloc_copy(doc) -> []; +realloc_copy(Cfg) -> ?line drv_case(Cfg). + +bucket_index(suite) -> []; +bucket_index(doc) -> []; +bucket_index(Cfg) -> ?line drv_case(Cfg). + +bucket_mask(suite) -> []; +bucket_mask(doc) -> []; +bucket_mask(Cfg) -> ?line drv_case(Cfg). + +rbtree(suite) -> []; +rbtree(doc) -> []; +rbtree(Cfg) -> ?line drv_case(Cfg). + +mseg_clear_cache(suite) -> []; +mseg_clear_cache(doc) -> []; +mseg_clear_cache(Cfg) -> ?line drv_case(Cfg). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %% +%% Internal functions %% +%% %% + +drv_case(Config) -> + drv_case(Config, ""). + +drv_case(Config, Command) when is_list(Config), + is_list(Command) -> + case ?t:os_type() of + {Family, _} when Family == unix; Family == win32 -> + ?line {ok, Node} = start_node(Config), + ?line Self = self(), + ?line Ref = make_ref(), + ?line spawn_link(Node, + fun () -> + Res = run_drv_case(Config, Command), + Self ! {Ref, Res} + end), + ?line Result = receive {Ref, Rslt} -> Rslt end, + ?line stop_node(Node), + ?line Result; + SkipOs -> + ?line {skipped, + lists:flatten(["Not run on " + | io_lib:format("~p",[SkipOs])])} + end. + +run_drv_case(Config, Command) -> + ?line DataDir = ?config(data_dir,Config), + ?line CaseName = ?config(testcase,Config), + case erl_ddll:load_driver(DataDir, CaseName) of + ok -> ok; + {error, Error} -> + io:format("~s\n", [erl_ddll:format_error(Error)]), + ?line ?t:fail() + end, + ?line Port = open_port({spawn, atom_to_list(CaseName)}, []), + ?line true = is_port(Port), + ?line Port ! {self(), {command, Command}}, + ?line Result = receive_drv_result(Port, CaseName), + ?line Port ! {self(), close}, + ?line receive + {Port, closed} -> + ok + end, + ?line ok = erl_ddll:unload_driver(CaseName), + ?line Result. + +receive_drv_result(Port, CaseName) -> + ?line receive + {print, Port, CaseName, Str} -> + ?line ?t:format("~s", [Str]), + ?line receive_drv_result(Port, CaseName); + {'EXIT', Port, Error} -> + ?line ?t:fail(Error); + {'EXIT', error, Error} -> + ?line ?t:fail(Error); + {failed, Port, CaseName, Comment} -> + ?line ?t:fail(Comment); + {skipped, Port, CaseName, Comment} -> + ?line {skipped, Comment}; + {succeeded, Port, CaseName, ""} -> + ?line succeeded; + {succeeded, Port, CaseName, Comment} -> + ?line {comment, Comment} + end. + +start_node(Config) when is_list(Config) -> + ?line Pa = filename:dirname(code:which(?MODULE)), + ?line {A, B, C} = now(), + ?line Name = list_to_atom(atom_to_list(?MODULE) + ++ "-" + ++ atom_to_list(?config(testcase, Config)) + ++ "-" + ++ integer_to_list(A) + ++ "-" + ++ integer_to_list(B) + ++ "-" + ++ integer_to_list(C)), + ?line ?t:start_node(Name, slave, [{args, "-pa "++Pa}]). + +stop_node(Node) -> + ?t:stop_node(Node). diff --git a/erts/emulator/test/alloc_SUITE_data/Makefile.src b/erts/emulator/test/alloc_SUITE_data/Makefile.src new file mode 100644 index 0000000000..035415d73e --- /dev/null +++ b/erts/emulator/test/alloc_SUITE_data/Makefile.src @@ -0,0 +1,41 @@ +# ``The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved via the world wide web at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# The Initial Developer of the Original Code is Ericsson Utvecklings AB. +# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings +# AB. All Rights Reserved.'' +# +# $Id$ +# + +TEST_DRVS = basic@dll@ \ + coalesce@dll@ \ + threads@dll@ \ + realloc_copy@dll@ \ + bucket_index@dll@ \ + bucket_mask@dll@ \ + rbtree@dll@ \ + mseg_clear_cache@dll@ + +CC = @CC@ +LD = @LD@ +CFLAGS = @SHLIB_CFLAGS@ -I@erl_include@ @DEFS@ +SHLIB_EXTRA_LDLIBS = testcase_driver@obj@ + +all: $(TEST_DRVS) + +@SHLIB_RULES@ + +testcase_driver@obj@: testcase_driver.c testcase_driver.h +$(TEST_DRVS): testcase_driver@obj@ allocator_test.h + + + diff --git a/erts/emulator/test/alloc_SUITE_data/allocator_test.h b/erts/emulator/test/alloc_SUITE_data/allocator_test.h new file mode 100644 index 0000000000..b869a4079c --- /dev/null +++ b/erts/emulator/test/alloc_SUITE_data/allocator_test.h @@ -0,0 +1,131 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#ifndef ALLOCATOR_TEST_H__ +#define ALLOCATOR_TEST_H__ + +typedef unsigned long Ulong; + +#ifndef __WIN32__ +Ulong erts_alc_test(Ulong, Ulong, Ulong, Ulong); +#endif + +#define UNDEF__ ~((Ulong) 0) + +#define ALC_TEST0(OP) \ + erts_alc_test((Ulong) (OP), UNDEF__, UNDEF__, UNDEF__) +#define ALC_TEST1(OP, A1) \ + erts_alc_test((Ulong) (OP), (Ulong) (A1), UNDEF__, UNDEF__) +#define ALC_TEST2(OP, A1, A2) \ + erts_alc_test((Ulong) (OP), (Ulong) (A1), (Ulong) (A2), UNDEF__) +#define ALC_TEST3(OP, A1, A2, A3) \ + erts_alc_test((Ulong) (OP), (Ulong) (A1), (Ulong) (A2), (Ulong) (A3)) + +typedef Ulong Block_t; +typedef Ulong Carrier_t; +typedef Ulong Allctr_t; +typedef Ulong RBT_t; +typedef Ulong RBTL_t; +typedef void* erts_thread; +typedef void* erts_mutex; +typedef void* erts_cond; + +/* From erl_alloc_util.c */ + +#define BLK_SZ(B) ((Ulong) ALC_TEST1(0x000, (B))) +#define UMEM_SZ(B) ((Ulong) ALC_TEST1(0x001, (B))) +#define IS_PREV_FREE_BLK(B) ((Ulong) ALC_TEST1(0x002, (B))) +#define IS_FREE_BLK(B) ((Ulong) ALC_TEST1(0x003, (B))) +#define IS_LAST_BLK(B) ((Ulong) ALC_TEST1(0x004, (B))) +#define UMEM2BLK(U) ((Block_t *) ALC_TEST1(0x005, (U))) +#define BLK2UMEM(B) ((void *) ALC_TEST1(0x006, (B))) +#define IS_SBC(C) ((Ulong) ALC_TEST1(0x007, (C))) +#define IS_SBC_BLK(B) ((Ulong) ALC_TEST1(0x008, (B))) +#define IS_MBC(C) ((Ulong) ALC_TEST1(0x009, (C))) +#define IS_MMAP_C(C) ((Ulong) ALC_TEST1(0x00a, (C))) +#define C_SZ(C) ((Ulong) ALC_TEST1(0x00b, (C))) +#define SBC2BLK(A, C) ((Block_t *) ALC_TEST2(0x00c, (A), (C))) +#define BLK2SBC(A, B) ((Carrier_t *) ALC_TEST2(0x00d, (A), (B))) +#define MBC2FBLK(A, C) ((Block_t *) ALC_TEST2(0x00e, (A), (C))) +#define FBLK2MBC(A, B) ((Carrier_t *) ALC_TEST2(0x00f, (A), (B))) +#define FIRST_MBC(A) ((Carrier_t *) ALC_TEST1(0x010, (A))) +#define LAST_MBC(A) ((Carrier_t *) ALC_TEST1(0x011, (A))) +#define FIRST_SBC(A) ((Carrier_t *) ALC_TEST1(0x012, (A))) +#define LAST_SBC(A) ((Carrier_t *) ALC_TEST1(0x013, (A))) +#define NEXT_C(C) ((Carrier_t *) ALC_TEST1(0x014, (C))) +#define PREV_C(C) ((Carrier_t *) ALC_TEST1(0x015, (C))) +#define ABLK_HDR_SZ ((Ulong) ALC_TEST0(0x016)) +#define MIN_BLK_SZ(A) ((Ulong) ALC_TEST1(0x017, (A))) +#define NXT_BLK(B) ((Block_t *) ALC_TEST1(0x018, (B))) +#define PREV_BLK(B) ((Block_t *) ALC_TEST1(0x019, (B))) +#define IS_FIRST_BLK(B) ((Ulong) ALC_TEST1(0x01a, (B))) +#define UNIT_SZ ((Ulong) ALC_TEST0(0x01b)) + +/* From erl_goodfit_alloc.c */ +#define BKT_IX(A, S) ((Ulong) ALC_TEST2(0x100, (A), (S))) +#define BKT_MIN_SZ(A, I) ((Ulong) ALC_TEST2(0x101, (A), (I))) +#define NO_OF_BKTS ((Ulong) ALC_TEST0(0x102)) +#define FIND_BKT(A, I) ((int) ALC_TEST2(0x103, (A), (I))) + +/* From erl_bestfit_alloc.c */ +#define IS_AOBF(A) ((Ulong) ALC_TEST1(0x200, (A))) +#define RBT_ROOT(A) ((RBT_t *) ALC_TEST1(0x201, (A))) +#define RBT_PARENT(T) ((RBT_t *) ALC_TEST1(0x202, (T))) +#define RBT_LEFT(T) ((RBT_t *) ALC_TEST1(0x203, (T))) +#define RBT_RIGHT(T) ((RBT_t *) ALC_TEST1(0x204, (T))) +#define RBT_NEXT(T) ((RBTL_t *) ALC_TEST1(0x205, (T))) +#define RBT_IS_BLACK(T) ((Ulong) ALC_TEST1(0x206, (T))) +#define RBT_IS_TREE(T) ((Ulong) ALC_TEST1(0x207, (T))) + +/* From erl_mseg.c */ +#define HAVE_MSEG() ((int) ALC_TEST0(0x400)) +#define MSEG_ALLOC(SP) ((void *) ALC_TEST1(0x401, (SP))) +#define MSEG_DEALLOC(P, S) ((void) ALC_TEST2(0x402, (P), (S))) +#define MSEG_REALLOC(P, OS, SP) ((void *) ALC_TEST3(0x403, (P), (OS), \ + (SP))) +#define MSEG_CLEAR_CACHE() ((void) ALC_TEST0(0x404)) +#define MSEG_NO() ((Ulong) ALC_TEST0(0x405)) +#define MSEG_CACHE_SIZE() ((Ulong) ALC_TEST0(0x406)) + +/* From erl_alloc.c */ + +#undef ALLOC +#undef REALLOC +#undef FREE + +#define ALLOC(A, S) ((void *) ALC_TEST2(0xf00, (A), (S))) +#define REALLOC(A, P, S) ((void *) ALC_TEST3(0xf01, (A), (P), (S))) +#define FREE(A, P) ((void) ALC_TEST2(0xf02, (A), (P))) +#define START_ALC(N, T, A) ((Allctr_t *) ALC_TEST3(0xf03, (N), (T), (A))) +#define STOP_ALC(A) ((void) ALC_TEST1(0xf04, (A))) +#define IS_THREADS_ENABLED ((int) ALC_TEST0(0xf05)) +#define IS_ALLOC_THREAD_SAFE(A) ((int) ALC_TEST1(0xf06, (A))) +#define IS_ALLOC_FORK_SAFE(A) ((int) ALC_TEST1(0xf07, (A))) +#define THR_MTX_CREATE() ((erts_mutex) ALC_TEST0(0xf08)) +#define THR_MTX_DESTROY(M) ((void) ALC_TEST1(0xf09, (M))) +#define THR_MTX_LOCK(M) ((void) ALC_TEST1(0xf0a, (M))) +#define THR_MTX_UNLOCK(M) ((void) ALC_TEST1(0xf0b, (M))) +#define THR_COND_CREATE() ((erts_cond) ALC_TEST0(0xf0c)) +#define THR_COND_DESTROY(C) ((void) ALC_TEST1(0xf0d, (C))) +#define THR_COND_BCAST(C) ((void) ALC_TEST1(0xf0e, (C))) +#define THR_COND_WAIT(C, M) ((void) ALC_TEST2(0xf0f, (C), (M))) +#define THR_CREATE(F, A) ((erts_thread) ALC_TEST2(0xf10, (F), (A))) +#define THR_JOIN(T) ((void) ALC_TEST1(0xf11, (T))) +#define THR_EXIT(R) ((void) ALC_TEST1(0xf12, (R))) + +#endif diff --git a/erts/emulator/test/alloc_SUITE_data/basic.c b/erts/emulator/test/alloc_SUITE_data/basic.c new file mode 100644 index 0000000000..4a5e888161 --- /dev/null +++ b/erts/emulator/test/alloc_SUITE_data/basic.c @@ -0,0 +1,61 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" +#include "allocator_test.h" + +char * +testcase_name(void) +{ + return "basic"; +} + +void +testcase_run(TestCaseState_t *tcs) +{ + Carrier_t *c; + Block_t *blk; + void *p; + Allctr_t *a = START_ALC("basic_", 0, NULL); + tcs->extra = (void *) a; + + ASSERT(tcs, a); + + p = ALLOC(a, 10); + ASSERT(tcs, p); + p = REALLOC(a, p, 15); + ASSERT(tcs, p); + FREE(a, p); + + c = FIRST_MBC(a); + ASSERT(tcs, !NEXT_C(c)); + blk = MBC2FBLK(a, c); + ASSERT(tcs, IS_LAST_BLK(blk)); + ASSERT(tcs, IS_FREE_BLK(blk)); + + STOP_ALC((Allctr_t *) a); + tcs->extra = NULL; + +} + +void +testcase_cleanup(TestCaseState_t *tcs) +{ + if (tcs->extra) + STOP_ALC((Allctr_t *) tcs->extra); +} diff --git a/erts/emulator/test/alloc_SUITE_data/bucket_index.c b/erts/emulator/test/alloc_SUITE_data/bucket_index.c new file mode 100644 index 0000000000..32fd16fc10 --- /dev/null +++ b/erts/emulator/test/alloc_SUITE_data/bucket_index.c @@ -0,0 +1,114 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" +#include "allocator_test.h" +#include <stdio.h> + +#define MAX_TEST_SIZE 100000000 + +char * +testcase_name(void) +{ + return "bucket_index"; +} + +void test_it(TestCaseState_t *tcs, unsigned sbct); + +void +testcase_run(TestCaseState_t *tcs) +{ + testcase_printf(tcs, "No of buckets = %lu:\n\n", NO_OF_BKTS); + + test_it(tcs, 1); + test_it(tcs, 0); + test_it(tcs, 1024); + test_it(tcs, 10240); +} + +void +testcase_cleanup(TestCaseState_t *tcs) +{ + if (tcs->extra) { + STOP_ALC(tcs->extra); + tcs->extra = NULL; + } +} + +void +test_it(TestCaseState_t *tcs, unsigned sbct) +{ + Ulong max_cont_test_sz; + char sbct_buf[21]; + char *argv[] = {"-tas", "gf", "-tsbct", NULL, NULL}; + int no_changes; + Ulong bi; + Ulong min_sz; + Ulong prev_bi; + Ulong sz; + Allctr_t *a; + + no_changes = 0; + prev_bi = -1; + + if (sbct) { + sprintf(sbct_buf, "%d", sbct); + argv[3] = sbct_buf; + } + else + argv[2] = NULL; + + max_cont_test_sz = 2*sbct*1024; + if (max_cont_test_sz < 1000000) + max_cont_test_sz = 1000000; + + testcase_printf(tcs, "Testing with sbct = %s\n", + sbct ? sbct_buf : "default"); + a = START_ALC("bkt_ix_", 0, argv); + tcs->extra = (void *) a; + ASSERT(tcs, a); + + sz = MIN_BLK_SZ(a); + while(sz < ((((Ulong)1) << 31) - 1)) { + bi = BKT_IX(a, sz); + if (prev_bi != bi) { + ASSERT(tcs, prev_bi + 1 == bi); + + min_sz = BKT_MIN_SZ(a, bi); + + ASSERT(tcs, sz == min_sz); + + testcase_printf(tcs, "sz=%d->ix=%d ", sz, bi); + no_changes++; + } + prev_bi = bi; + if (sz < max_cont_test_sz) + sz++; + else + sz += 100000000; + } + testcase_printf(tcs, "\n\n"); + ASSERT(tcs, no_changes == NO_OF_BKTS); + + STOP_ALC(a); + tcs->extra = NULL; + + testcase_printf(tcs, "Test with sbct=%s succeeded\n", + sbct ? sbct_buf : "default"); +} + diff --git a/erts/emulator/test/alloc_SUITE_data/bucket_mask.c b/erts/emulator/test/alloc_SUITE_data/bucket_mask.c new file mode 100644 index 0000000000..13af7d861a --- /dev/null +++ b/erts/emulator/test/alloc_SUITE_data/bucket_mask.c @@ -0,0 +1,147 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" +#include "allocator_test.h" +#include <stdio.h> + +#define SBCT (512*1024) + +char * +testcase_name(void) +{ + return "bucket_mask"; +} + +void +testcase_cleanup(TestCaseState_t *tcs) +{ + if (tcs->extra) { + STOP_ALC(tcs->extra); + tcs->extra = NULL; + } +} + +void +testcase_run(TestCaseState_t *tcs) +{ + void *tmp; + void **fence; + void **blk; + Ulong sz; + Ulong smbcs; + int i; + int bi; + int bi_tests; + Ulong sbct = (SBCT/1024)*1024; + Ulong min_blk_sz; + Ulong ablk_hdr_sz = ABLK_HDR_SZ; + char smbcs_buf[30]; + char sbct_buf[30]; + int no_bkts = (int) NO_OF_BKTS; + char *argv1[] = {"-tasgf", "-tmmbcs0", sbct_buf, NULL}; + char *argv2[] = {"-tasgf", "-tmmbcs0", sbct_buf, NULL, NULL}; + Allctr_t *a; + + sprintf(sbct_buf, "-tsbct%lu", sbct/1024); + + a = START_ALC("bkt_mask_1_", 0, argv1); + tcs->extra = (void *) a; + ASSERT(tcs, a); + + min_blk_sz = MIN_BLK_SZ(a); + smbcs = 2*(no_bkts*sizeof(void *) + min_blk_sz) + min_blk_sz; + for (i = 0; i < no_bkts; i++) { + sz = BKT_MIN_SZ(a, i); + if (sz >= sbct) + break; + smbcs += sz + min_blk_sz; + } + + bi_tests = i; + testcase_printf(tcs, "Will test %d buckets\n", bi_tests); + + STOP_ALC(a); + tcs->extra = NULL; + + smbcs /= 1024; + smbcs++; + + testcase_printf(tcs, "smbcs = %lu\n", smbcs); + sprintf(smbcs_buf, "-tsmbcs%lu", smbcs); + argv2[3] = smbcs_buf; + + a = START_ALC("bkt_mask_2_", 0, argv2); + tcs->extra = (void *) a; + ASSERT(tcs, a); + + blk = (void **) ALLOC(a, no_bkts*sizeof(void *)); + fence = (void **) ALLOC(a, no_bkts*sizeof(void *)); + + ASSERT(tcs, blk && fence); + + testcase_printf(tcs, "Allocating blocks and fences\n"); + for (i = 0; i < bi_tests; i++) { + sz = BKT_MIN_SZ(a, i); + blk[i] = ALLOC(a, sz - ablk_hdr_sz); + fence[i] = ALLOC(a, 1); + ASSERT(tcs, blk[i] && fence[i]); + } + + tmp = (void *) UMEM2BLK(fence[bi_tests - 1]); + tmp = (void *) NXT_BLK((Block_t *) tmp); + ASSERT(tcs, IS_LAST_BLK(tmp)); + sz = BLK_SZ((Block_t *) tmp); + testcase_printf(tcs, "Allocating leftover size = %lu\n", sz); + tmp = ALLOC(a, sz - ablk_hdr_sz); + ASSERT(tcs, tmp); + + bi = FIND_BKT(a, 0); + ASSERT(tcs, bi < 0); + + for (i = 0; i < bi_tests; i++) { + sz = BKT_MIN_SZ(a, i); + testcase_printf(tcs, "Testing bucket %d\n", i); + FREE(a, blk[i]); + bi = FIND_BKT(a, i); + ASSERT(tcs, bi == i); + blk[i] = ALLOC(a, sz - ablk_hdr_sz); + bi = FIND_BKT(a, i); + ASSERT(tcs, bi != i); + } + + for (i = 0; i < bi_tests; i++) { + FREE(a, blk[i]); + FREE(a, fence[i]); + } + + FREE(a, (void *) blk); + FREE(a, (void *) fence); + + bi = FIND_BKT(a, 0); + ASSERT(tcs, bi == no_bkts - 1); + + FREE(a, tmp); + + bi = FIND_BKT(a, 0); + ASSERT(tcs, bi < 0); + + STOP_ALC(a); + tcs->extra = NULL; +} + diff --git a/erts/emulator/test/alloc_SUITE_data/coalesce.c b/erts/emulator/test/alloc_SUITE_data/coalesce.c new file mode 100644 index 0000000000..c84da97d35 --- /dev/null +++ b/erts/emulator/test/alloc_SUITE_data/coalesce.c @@ -0,0 +1,318 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" +#include "allocator_test.h" +#include <string.h> + +#define CEILING(X, U) ((((X)+(U)-1)/(U))*(U)) + +void +check_ablk(TestCaseState_t *tcs, Allctr_t *a, void *ptr, Ulong umem_sz) +{ + Ulong unit_sz = UNIT_SZ; + Block_t *blk = UMEM2BLK(ptr); + Block_t *nxt_blk = NXT_BLK(blk); + Ulong real_sz = ((Ulong) nxt_blk) - ((Ulong) (blk)); + ASSERT(tcs, real_sz == BLK_SZ(blk)); + ASSERT(tcs, !IS_FREE_BLK(blk)); + ASSERT(tcs, real_sz >= CEILING(ABLK_HDR_SZ + umem_sz, unit_sz)); + if (real_sz > MIN_BLK_SZ(a) + && real_sz > CEILING(ABLK_HDR_SZ+umem_sz, unit_sz)) { + ASSERT(tcs, + real_sz <= CEILING(MIN_BLK_SZ(a)+ABLK_HDR_SZ+umem_sz, + unit_sz)); + ASSERT(tcs, IS_LAST_BLK(blk) || !IS_FREE_BLK(nxt_blk)); + } +} + +void +setup_sequence(TestCaseState_t *tcs, Allctr_t *a, Ulong bsz, int no, + void *res[]) +{ + Carrier_t *c; + Block_t *blk; + int i; + + testcase_printf(tcs, + "Setting up a sequence of %d blocks of size %lu\n", + no, bsz); + c = FIRST_MBC(a); + ASSERT(tcs, !NEXT_C(c)); + blk = MBC2FBLK(a, c); + ASSERT(tcs, IS_LAST_BLK(blk)); + + for (i = 0; i < no; i++) + res[i] = ALLOC(a, bsz); + for (i = 0; i < no; i++) + ASSERT(tcs, res[i]); + + testcase_printf(tcs, "Checking that sequence was set up as expected\n"); + + for (i = 1; i < no; i++) + ASSERT(tcs, NXT_BLK(UMEM2BLK(res[i-1])) == UMEM2BLK(res[i])); + + blk = NXT_BLK(UMEM2BLK(res[no-1])); + ASSERT(tcs, IS_LAST_BLK(blk)); + + testcase_printf(tcs, "Sequence ok\n"); + + /* If we fail in setup_sequence(), it doesn't mean that something is + wrong. It is just a faulty assumption in setup_sequence() about + how blocks are going to be placed. + Fix setup_sequence()... */ +} + +static void +test_free(TestCaseState_t *tcs, Allctr_t *a, Ulong bsz) +{ + Block_t *blk; + void *p[7]; + + testcase_printf(tcs," --- Testing free() with block size %lu ---\n",bsz); + + setup_sequence(tcs, a, bsz, 7, p); + + check_ablk(tcs, a, p[0], bsz); + check_ablk(tcs, a, p[1], bsz); + check_ablk(tcs, a, p[2], bsz); + check_ablk(tcs, a, p[3], bsz); + check_ablk(tcs, a, p[4], bsz); + check_ablk(tcs, a, p[5], bsz); + check_ablk(tcs, a, p[6], bsz); + + /* Coalescing with previous block */ + FREE(a, p[2]); + FREE(a, p[3]); + + blk = NXT_BLK(UMEM2BLK(p[1])); + ASSERT(tcs, IS_FREE_BLK(blk)); + ASSERT(tcs, NXT_BLK(blk) == UMEM2BLK(p[4])); + + /* Coalescing with next block */ + + FREE(a, p[1]); + blk = NXT_BLK(UMEM2BLK(p[0])); + ASSERT(tcs, IS_FREE_BLK(blk)); + ASSERT(tcs, NXT_BLK(blk) == UMEM2BLK(p[4])); + + /* Coalescing with next and previous block */ + + FREE(a, p[5]); + FREE(a, p[4]); + + blk = NXT_BLK(UMEM2BLK(p[0])); + ASSERT(tcs, IS_FREE_BLK(blk)); + ASSERT(tcs, NXT_BLK(blk) == UMEM2BLK(p[6])); + + /* Cleanup */ + + FREE(a, p[0]); + FREE(a, p[6]); + + testcase_printf(tcs," --- free() with block size %lu succeded ---\n",bsz); +} + +static void +test_realloc(TestCaseState_t *tcs, Allctr_t *a, Ulong bsz) +{ + Block_t *blk; + void *ptr; + void *p[3]; + Ulong nbsz; + + testcase_printf(tcs," --- Testing realloc() with block size %lu ---\n", + bsz); + + setup_sequence(tcs, a, bsz, 3, p); + + check_ablk(tcs, a, p[0], bsz); + check_ablk(tcs, a, p[1], bsz); + check_ablk(tcs, a, p[2], bsz); + + /* Grow to the end of the carrier */ + blk = NXT_BLK(UMEM2BLK(p[2])); + ASSERT(tcs, IS_FREE_BLK(blk)); + ASSERT(tcs, IS_LAST_BLK(blk)); + nbsz = bsz + BLK_SZ(blk); + ptr = REALLOC(a, p[2], nbsz); + ASSERT(tcs, p[2] == ptr); + check_ablk(tcs, a, p[2], nbsz); + blk = UMEM2BLK(p[2]); + ASSERT(tcs, IS_LAST_BLK(blk)); + + /* Shrink from the end of the carrier */ + ptr = REALLOC(a, p[2], bsz); + ASSERT(tcs, p[2] == ptr); + blk = UMEM2BLK(p[2]); + ASSERT(tcs, !IS_LAST_BLK(blk)); + blk = NXT_BLK(blk); + ASSERT(tcs, IS_LAST_BLK(blk)); + check_ablk(tcs, a, p[2], bsz); + + /* Shrink and coalecse with next free */ + + FREE(a, p[1]); + + blk = NXT_BLK(UMEM2BLK(p[0])); + ASSERT(tcs, IS_FREE_BLK(blk)); + + nbsz = bsz/2; + ptr = REALLOC(a, p[0], nbsz); + ASSERT(tcs, p[0] == ptr); + + check_ablk(tcs, a, p[0], nbsz); + + blk = NXT_BLK(UMEM2BLK(p[0])); + ASSERT(tcs, IS_FREE_BLK(blk)); + ASSERT(tcs, NXT_BLK(blk) == UMEM2BLK(p[2])); + + /* Grow into next free; but leave free block at end */ + + nbsz *= 3; + ptr = REALLOC(a, p[0], nbsz); + ASSERT(tcs, p[0] == ptr); + + check_ablk(tcs, a, p[0], nbsz); + blk = NXT_BLK(UMEM2BLK(p[0])); + + ASSERT(tcs, IS_FREE_BLK(blk)); + ASSERT(tcs, NXT_BLK(blk) == UMEM2BLK(p[2])); + + /* Grow upto next alloced block by allocating just enough so that no + free block fits between them */ + nbsz = BLK_SZ(blk) + UMEM_SZ(UMEM2BLK(p[0])); + nbsz -= MIN_BLK_SZ(a) - 1; + + ptr = REALLOC(a, p[0], nbsz); + ASSERT(tcs, p[0] == ptr); + check_ablk(tcs, a, p[0], nbsz); + blk = NXT_BLK(UMEM2BLK(p[0])); + ASSERT(tcs, !IS_FREE_BLK(blk)); + ASSERT(tcs, blk == UMEM2BLK(p[2])); + + /* Grow into unused part at end */ + nbsz += MIN_BLK_SZ(a) - 1; + ptr = REALLOC(a, p[0], nbsz); + ASSERT(tcs, p[0] == ptr); + check_ablk(tcs, a, p[0], nbsz); + ASSERT(tcs, !IS_FREE_BLK(blk)); + ASSERT(tcs, blk == UMEM2BLK(p[2])); + + /* Shrink *almost* as much so that a free block would fit between the + allocated blocks, and make sure that we don't get a free block + in between */ + nbsz -= MIN_BLK_SZ(a) - 1; + ptr = REALLOC(a, p[0], nbsz); + ASSERT(tcs, p[0] == ptr); + check_ablk(tcs, a, p[0], nbsz); + blk = NXT_BLK(UMEM2BLK(p[0])); + ASSERT(tcs, !IS_FREE_BLK(blk)); + ASSERT(tcs, blk == UMEM2BLK(p[2])); + + /* Shrink just as much so that a free block can fit between + the alloced blocks */ + nbsz -= 1; + ptr = REALLOC(a, p[0], nbsz); + ASSERT(tcs, p[0] == ptr); + check_ablk(tcs, a, p[0], nbsz); + blk = NXT_BLK(UMEM2BLK(p[0])); + ASSERT(tcs, IS_FREE_BLK(blk)); + ASSERT(tcs, blk < UMEM2BLK(p[2])); + ASSERT(tcs, NXT_BLK(blk) == UMEM2BLK(p[2])); + + /* Shrink so little that no free block would fit between allocated + blocks, and make sure that we shrink the allocated block and + coalesce the extra free part with the next free block. */ + nbsz -= MIN_BLK_SZ(a) - 1; + ptr = REALLOC(a, p[0], nbsz); + ASSERT(tcs, p[0] == ptr); + check_ablk(tcs, a, p[0], nbsz); + blk = NXT_BLK(UMEM2BLK(p[0])); + ASSERT(tcs, IS_FREE_BLK(blk)); + ASSERT(tcs, blk < UMEM2BLK(p[2])); + ASSERT(tcs, NXT_BLK(blk) == UMEM2BLK(p[2])); + + /* Cleanup */ + FREE(a, p[0]); + FREE(a, p[2]); + + testcase_printf(tcs, " --- realloc() with block size %lu succeded ---\n", + bsz); + +} + +char * +testcase_name(void) +{ + return "coalesce"; +} + +void +testcase_run(TestCaseState_t *tcs) +{ + char *argv_org[] = {"-tmmbcs1024", "-tsbct2048", "-trmbcmt100", "-tas", NULL, NULL}; + char *alg[] = {"af", "gf", "bf", "aobf", NULL}; + int i; + + for (i = 0; alg[i]; i++) { + Ulong sz; + Allctr_t *a; + char *argv[sizeof(argv_org)/sizeof(argv_org[0])]; + memcpy((void *) argv, (void *) argv_org, sizeof(argv_org)); + + argv[4] = alg[i]; + testcase_printf(tcs, " *** Starting \"%s\" allocator *** \n", alg[i]); + a = START_ALC("coalesce_", 0, argv); + ASSERT(tcs, a); + tcs->extra = (void *) a; + + sz = MIN_BLK_SZ(a) - ABLK_HDR_SZ; + test_free(tcs, a, sz); + sz += 1; + test_free(tcs, a, sz); + sz *= 4; + test_free(tcs, a, sz); + sz += 1; + test_free(tcs, a, sz); + sz *= 10; + test_free(tcs, a, sz); + + sz = MIN_BLK_SZ(a)*4 - ABLK_HDR_SZ; + test_realloc(tcs, a, sz); + sz += 1; + test_realloc(tcs, a, sz); + sz *= 4; + test_realloc(tcs, a, sz); + sz += 1; + test_realloc(tcs, a, sz); + sz *= 10; + test_realloc(tcs, a, sz); + + testcase_printf(tcs, " *** Stopping \"%s\" allocator *** \n", alg[i]); + STOP_ALC(a); + tcs->extra = NULL; + } +} + +void +testcase_cleanup(TestCaseState_t *tcs) +{ + if (tcs->extra) + STOP_ALC((Allctr_t *) tcs->extra); +} diff --git a/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.c b/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.c new file mode 100644 index 0000000000..0277616bd0 --- /dev/null +++ b/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.c @@ -0,0 +1,102 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" +#include "allocator_test.h" + +#define MAX_SEGS 10 + +typedef struct { + void *ptr; + Ulong size; +} seg_t; + +char * +testcase_name(void) +{ + return "mseg_clear_cache"; +} + +void +testcase_run(TestCaseState_t *tcs) +{ + int i; + Ulong n; + seg_t *seg; + + if (!HAVE_MSEG()) + testcase_skipped(tcs, "No mseg_alloc; nothing to test"); + + seg = (seg_t *) testcase_alloc(sizeof(seg_t)*(MAX_SEGS+1)); + + ASSERT(tcs, seg); + + for (i = 0; i <= MAX_SEGS; i++) + seg[i].ptr = NULL; + + tcs->extra = &seg[0]; + + for (i = 0; i < MAX_SEGS; i++) { + seg[i].size = 1000; + seg[i].ptr = MSEG_ALLOC(&seg[i].size); + ASSERT(tcs, seg[i].ptr); + ASSERT(tcs, seg[i].size >= 1000); + } + + n = MSEG_NO(); + testcase_printf(tcs, "MSEG_NO() = %lu\n", n); + + ASSERT(tcs, n >= MAX_SEGS); + + testcase_printf(tcs, "Deallocating half of the segments\n"); + for (i = MAX_SEGS-1; i >= MAX_SEGS/2; i--) { + MSEG_DEALLOC(seg[i].ptr, seg[i].size); + seg[i].ptr = NULL; + } + + n = MSEG_NO(); + testcase_printf(tcs, "MSEG_NO() = %lu\n", n); + + ASSERT(tcs, n >= MAX_SEGS/2); + + n = MSEG_CACHE_SIZE(); + testcase_printf(tcs, "MSEG_CACHE_SIZE() = %lu\n", n); + ASSERT(tcs, n > 0); + + testcase_printf(tcs, "MSEG_CLEAR_CACHE()\n"); + MSEG_CLEAR_CACHE(); + + n = MSEG_CACHE_SIZE(); + testcase_printf(tcs, "MSEG_CACHE_SIZE() = %lu\n", n); + + ASSERT(tcs, n == 0); + +} + +void +testcase_cleanup(TestCaseState_t *tcs) +{ + if (tcs->extra) { + seg_t *seg = (seg_t *) tcs->extra; + int i; + for (i = 0; seg[i].ptr; i++) + MSEG_DEALLOC(seg[i].ptr, seg[i].size); + testcase_free((void *) seg); + tcs->extra = NULL; + } +} diff --git a/erts/emulator/test/alloc_SUITE_data/rbtree.c b/erts/emulator/test/alloc_SUITE_data/rbtree.c new file mode 100644 index 0000000000..c97e0aac1a --- /dev/null +++ b/erts/emulator/test/alloc_SUITE_data/rbtree.c @@ -0,0 +1,386 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" +#include "allocator_test.h" + +#define NO_BLOCKS 100000 + +#define RIGHT_VISITED (1 << 0) +#define LEFT_VISITED (1 << 1) + +typedef struct { + Allctr_t *allocator; + void **blk; + void **fence; +} rbtree_test_data; + +#if 0 +#define PRINT_TREE +#endif + +#ifdef PRINT_TREE + +#define INDENT_STEP 5 + +#include <stdio.h> +static void +print_tree_aux(TestCaseState_t *tcs, RBT_t *x, int indent) +{ + if (!x) { + char frmt[20]; + sprintf(frmt, "%%%ds%%s\n", indent); + testcase_printf(tcs, frmt, "", "BLACK: nil"); + } + else { + print_tree_aux(tcs, RBT_RIGHT(x), indent + INDENT_STEP); + { + char frmt[40]; + sprintf(frmt, "%%%ds%%s: sz=%%lu addr=0x%%lx\n", indent); + testcase_printf(tcs, + frmt, + "", + RBT_IS_BLACK(x) ? "BLACK" : "RED", + BLK_SZ(x), + (Ulong) x); + } + print_tree_aux(tcs, RBT_LEFT(x), indent + INDENT_STEP); + } +} + + +static void +print_tree(TestCaseState_t *tcs, RBT_t *root, int aobf) +{ + char *type = aobf ? "Size-Adress" : "Size"; + testcase_printf(tcs, " --- %s tree begin ---\r\n", type); + print_tree_aux(tcs, root, 0); + testcase_printf(tcs, " --- %s tree end ---\r\n", type); +} + +#endif + +static RBT_t * +check_tree(TestCaseState_t *tcs, Allctr_t *alc, Ulong size) +{ + int i, max_i, address_order; + char stk[128]; + RBT_t *root, *x, *y, *res; + Ulong x_sz, y_sz, is_x_black; + long blacks, curr_blacks; + + res = NULL; + + address_order = IS_AOBF(alc); + root = RBT_ROOT(alc); + +#ifdef PRINT_TREE + print_tree(tcs, root, address_order); +#endif + + max_i = i = -1; + curr_blacks = 0; + blacks = -1; + + if (!root) + goto done; + + stk[++i] = 0; + + ASSERT(tcs, RBT_IS_BLACK(root)); + ASSERT(tcs, !RBT_PARENT(root)); + x = root; + curr_blacks++; + + while (x) { + + ASSERT(tcs, i <= 128); + + if (!(stk[i] & LEFT_VISITED)) { + stk[i] |= LEFT_VISITED; + y = RBT_LEFT(x); + if (RBT_IS_BLACK(y)) + curr_blacks++; + if (y) { + x = y; + stk[++i] = 0; + continue; + } + else { + if (blacks < 0) + blacks = curr_blacks; + ASSERT(tcs, blacks == curr_blacks); + curr_blacks--; + } + } + + if (!(stk[i] & RIGHT_VISITED)) { + stk[i] |= RIGHT_VISITED; + y = RBT_RIGHT(x); + if (RBT_IS_BLACK(y)) + curr_blacks++; + if (y) { + x = y; + stk[++i] = 0; + continue; + } + else { + if (blacks < 0) + blacks = curr_blacks; + ASSERT(tcs, blacks == curr_blacks); + curr_blacks--; + } + } + + + /* Check x ... */ + + is_x_black = RBT_IS_BLACK(x); + x_sz = BLK_SZ(x); + + + if (!is_x_black) { + ASSERT(tcs, RBT_IS_BLACK(RBT_RIGHT(x))); + ASSERT(tcs, RBT_IS_BLACK(RBT_LEFT(x))); + } + + ASSERT(tcs, RBT_PARENT(x) || x == root); + + y = RBT_LEFT(x); + if (y) { + y_sz = BLK_SZ(y); + ASSERT(tcs, RBT_PARENT(y) == x); + if (address_order) { + ASSERT(tcs, y_sz < x_sz || (y_sz == x_sz && y < x)); + } + else { + ASSERT(tcs, RBT_IS_TREE(y)); + ASSERT(tcs, y_sz < x_sz); + } + } + + y = RBT_RIGHT(x); + if (y) { + y_sz = BLK_SZ(y); + ASSERT(tcs, RBT_PARENT(y) == x); + if (address_order) { + ASSERT(tcs, y_sz > x_sz || (y_sz == x_sz && y > x)); + } + else { + ASSERT(tcs, RBT_IS_TREE(y)); + ASSERT(tcs, y_sz > x_sz); + } + } + + if (!address_order) { + Ulong l_sz; + RBTL_t *l = RBT_NEXT(x); + for (l = RBT_NEXT(x); l; l = RBT_NEXT(l)) { + l_sz = BLK_SZ(l); + ASSERT(tcs, l_sz == x_sz); + ASSERT(tcs, !RBT_IS_TREE(l)); + } + } + + if (size && x_sz >= size) { + if (!res) + res = x; + else { + y_sz = BLK_SZ(res); + if (address_order) { + if (x_sz < y_sz || (x_sz == y_sz && x < res)) + res = x; + } + else { + if (!res || x_sz < y_sz) + res = x; + } + } + } + + if (max_i < i) + max_i = i; + if (is_x_black) + curr_blacks--; + x = RBT_PARENT(x); + i--; + } + + done: + ASSERT(tcs, curr_blacks == 0); + ASSERT(tcs, i == -1); + + testcase_printf(tcs, "Red-Black Tree OK! Max depth = %d; " + "Black depth = %d\n", max_i+1, blacks < 0 ? 0 : blacks); + + return res; + +} + +static void +do_check(TestCaseState_t *tcs, Allctr_t *a, Ulong size) +{ + Ulong sz = ((size + 7) / 8)*8; + void *tmp; + Block_t *x, *y; + + x = (Block_t *) check_tree(tcs, a, sz); + tmp = ALLOC(a, sz - ABLK_HDR_SZ); + ASSERT(tcs, tmp); + y = UMEM2BLK(tmp); + if (IS_AOBF(a)) { + ASSERT(tcs, x == y); + } + else { + ASSERT(tcs, BLK_SZ(x) == BLK_SZ(y)); + } + FREE(a, tmp); +} + + +static void +test_it(TestCaseState_t *tcs) +{ + int i; + Allctr_t a = ((rbtree_test_data *) tcs->extra)->allocator; + void **blk = ((rbtree_test_data *) tcs->extra)->blk; + void **fence = ((rbtree_test_data *) tcs->extra)->fence; + Ulong min_blk_sz; + + min_blk_sz = MIN_BLK_SZ(a); + + for (i = 0; i < NO_BLOCKS; i++) { + blk[i] = ALLOC(a, min_blk_sz + i % 500); + fence[i] = ALLOC(a, 1); + ASSERT(tcs, blk[i] && fence[i]); + } + + for (i = 0; i < NO_BLOCKS; i++) { + if (i % 3 == 0) { + FREE(a, blk[i]); + blk[i] = NULL; + } + if (i % (NO_BLOCKS/2) == 0) + do_check(tcs, a, 50); + } + + for (i = 0; i < NO_BLOCKS; i++) { + if (i % 5 == 0 && blk[i]) { + FREE(a, blk[i]); + blk[i] = NULL; + } + if (i % (NO_BLOCKS/2) == 0) + do_check(tcs, a, 200); + } + + for (i = 0; i < NO_BLOCKS; i++) { + if (blk[i]) { + FREE(a, blk[i]); + blk[i] = NULL; + } + if (i % (NO_BLOCKS/2) == 0) + do_check(tcs, a, 100); + } + + do_check(tcs, a, 250); + + for (i = 0; i < NO_BLOCKS; i++) { + FREE(a, fence[i]); + if (i % (NO_BLOCKS/3) == 0) + do_check(tcs, a, 300); + } + + ASSERT(tcs, RBT_ROOT(a)); + ASSERT(tcs, !RBT_LEFT(RBT_ROOT(a))); + ASSERT(tcs, !RBT_RIGHT(RBT_ROOT(a))); +} + + +char * +testcase_name(void) +{ + return "rbtree"; +} + +void +testcase_cleanup(TestCaseState_t *tcs) +{ + if (tcs->extra) { + rbtree_test_data *td = tcs->extra; + tcs->extra = NULL; + if (td->allocator) + STOP_ALC(td->allocator); + if (td->blk) + testcase_free((void *) td->blk); + if (td->fence) + testcase_free((void *) td->fence); + testcase_free((void *) td); + } +} + +void +testcase_run(TestCaseState_t *tcs) +{ + char *argv1[] = {"-tasbf", NULL}; + char *argv2[] = {"-tasaobf", NULL}; + Allctr_t *a; + rbtree_test_data *td; + + /* Best fit... */ + + testcase_printf(tcs, "Setup...\n"); + + td = (rbtree_test_data *) testcase_alloc(sizeof(rbtree_test_data)); + ASSERT(tcs, td); + tcs->extra = (void *) td; + td->allocator = NULL; + td->blk = (void **) testcase_alloc(sizeof(void *)*NO_BLOCKS); + td->fence = (void **) testcase_alloc(sizeof(void *)*NO_BLOCKS); + ASSERT(tcs, td->blk && td->fence); + + testcase_printf(tcs, "Starting test of best fit...\n"); + + td->allocator = a = START_ALC("rbtree_bf_", 0, argv1); + + ASSERT(tcs, a); + ASSERT(tcs, !IS_AOBF(a)); + + test_it(tcs); + + STOP_ALC(a); + td->allocator = NULL; + + testcase_printf(tcs, "Best fit test succeeded!\n"); + + /* Address order best fit... */ + + testcase_printf(tcs, "Starting test of address order best fit...\n"); + + td->allocator = a = START_ALC("rbtree_aobf_", 0, argv2); + + ASSERT(tcs, a); + ASSERT(tcs, IS_AOBF(a)); + + test_it(tcs); + + STOP_ALC(a); + td->allocator = NULL; + + testcase_printf(tcs, "Address order best fit test succeeded!\n"); + +} diff --git a/erts/emulator/test/alloc_SUITE_data/realloc_copy.c b/erts/emulator/test/alloc_SUITE_data/realloc_copy.c new file mode 100644 index 0000000000..12454c75e4 --- /dev/null +++ b/erts/emulator/test/alloc_SUITE_data/realloc_copy.c @@ -0,0 +1,279 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" +#include "allocator_test.h" +#include <stdio.h> +#include <string.h> + +#if 1 +#define PRINT_ALLOC_OPS +#endif + +#define SBC_THRESHOLD 8192 +#define NO_OF_BLOCKS 7 +#define NO_OF_ALLOC_OPS_PER_BLOCK 700 + +typedef struct { + unsigned char *p; + Ulong s; + int i; + Ulong *as; +} block; + +Ulong alloc_seq_1[] = { + SBC_THRESHOLD, /* mmap */ + SBC_THRESHOLD*4, /* mmap to new mmap */ + SBC_THRESHOLD/50, /* mmap to malloc */ + SBC_THRESHOLD, /* malloc to mmap */ + 0 +}; + + +Ulong alloc_seq_2[] = { + 1, + SBC_THRESHOLD/10, + SBC_THRESHOLD/9, + SBC_THRESHOLD/8, + SBC_THRESHOLD/7, + SBC_THRESHOLD/6, + SBC_THRESHOLD/5, + SBC_THRESHOLD/4, + SBC_THRESHOLD/3, + SBC_THRESHOLD/2, + SBC_THRESHOLD*1, + SBC_THRESHOLD*2, + SBC_THRESHOLD*3, + SBC_THRESHOLD*4, + SBC_THRESHOLD*5, + SBC_THRESHOLD*6, + SBC_THRESHOLD*7, + SBC_THRESHOLD*8, + SBC_THRESHOLD*9, + SBC_THRESHOLD*10, + SBC_THRESHOLD*9, + SBC_THRESHOLD*8, + SBC_THRESHOLD*7, + SBC_THRESHOLD*6, + SBC_THRESHOLD*5, + SBC_THRESHOLD*4, + SBC_THRESHOLD*3, + SBC_THRESHOLD*2, + SBC_THRESHOLD*1, + SBC_THRESHOLD/2, + SBC_THRESHOLD/3, + SBC_THRESHOLD/4, + SBC_THRESHOLD/5, + SBC_THRESHOLD/6, + SBC_THRESHOLD/7, + SBC_THRESHOLD/8, + SBC_THRESHOLD/9, + SBC_THRESHOLD/10, + 1, + 0 +}; + +Ulong alloc_seq_3[] = { + SBC_THRESHOLD*11, + SBC_THRESHOLD*10, + SBC_THRESHOLD*9, + SBC_THRESHOLD*8, + SBC_THRESHOLD*7, + SBC_THRESHOLD*6, + SBC_THRESHOLD*5, + SBC_THRESHOLD*4, + SBC_THRESHOLD*3, + SBC_THRESHOLD*2, + SBC_THRESHOLD*1, + SBC_THRESHOLD/2, + SBC_THRESHOLD/3, + SBC_THRESHOLD/4, + SBC_THRESHOLD/5, + SBC_THRESHOLD/6, + SBC_THRESHOLD/7, + SBC_THRESHOLD/8, + SBC_THRESHOLD/9, + SBC_THRESHOLD/10, + 1, + SBC_THRESHOLD/10, + SBC_THRESHOLD/9, + SBC_THRESHOLD/8, + SBC_THRESHOLD/7, + SBC_THRESHOLD/6, + SBC_THRESHOLD/5, + SBC_THRESHOLD/4, + SBC_THRESHOLD/3, + SBC_THRESHOLD/2, + SBC_THRESHOLD*1, + SBC_THRESHOLD*2, + SBC_THRESHOLD*3, + SBC_THRESHOLD*4, + SBC_THRESHOLD*5, + SBC_THRESHOLD*6, + SBC_THRESHOLD*7, + SBC_THRESHOLD*8, + SBC_THRESHOLD*9, + SBC_THRESHOLD*10, + 0 +}; + +Ulong alloc_seq_4[] = { + SBC_THRESHOLD*1, + SBC_THRESHOLD*10, + SBC_THRESHOLD*1, + 0 +}; + +Ulong alloc_seq_5[] = { + SBC_THRESHOLD/50, + SBC_THRESHOLD*10, + SBC_THRESHOLD/50, + 0 +}; + +Ulong alloc_seq_6[] = { + SBC_THRESHOLD/50, + SBC_THRESHOLD*10, + SBC_THRESHOLD/50, + SBC_THRESHOLD*10, + 0 +}; + +Ulong alloc_seq_7[] = { + 1, + SBC_THRESHOLD/50, + SBC_THRESHOLD*10, + SBC_THRESHOLD/50, + 0 +}; + + +block blocks[NO_OF_BLOCKS] = {{NULL, 0, 0, alloc_seq_1}, + {NULL, 0, 0, alloc_seq_2}, + {NULL, 0, 0, alloc_seq_3}, + {NULL, 0, 0, alloc_seq_4}, + {NULL, 0, 0, alloc_seq_5}, + {NULL, 0, 0, alloc_seq_6}, + {NULL, 0, 0, alloc_seq_7}}; + +#define CHECK_BLOCK_DATA(T, P, S, D) \ + check_block_data(__FILE__, __LINE__, (T), (P), (S), (D)) + +static void +check_block_data(char *file, int line, + TestCaseState_t *tcs, unsigned char *p, Ulong sz, int d) +{ + Ulong i; + for (i = 0; i < sz; i++) + if (p[i] != (unsigned char) d) + testcase_failed(tcs, "%s:%d: Data clobbered! found id=%d; " + "expected id=%d\n", file, line, (int) p[i], d); +} + + +static void +alloc_op(TestCaseState_t *tcs, Allctr_t *a, block *bp, int id, int clean_up) +{ + if(bp->p) + CHECK_BLOCK_DATA(tcs, bp->p, bp->s, id); + + if(bp->as[bp->i] == 0 || clean_up) { + FREE(a, bp->p); +#ifdef PRINT_ALLOC_OPS + testcase_printf(tcs, "FREE(0x%lx) [id=%d]\n", (Ulong) bp->p, id); +#endif + bp->p = NULL; + bp->s = 0; + bp->i = 0; /* start from the beginning again */ + return; + } + + if(!bp->p) { + bp->s = bp->as[bp->i]; + bp->p = (unsigned char *) ALLOC(a, bp->s); +#ifdef PRINT_ALLOC_OPS + testcase_printf(tcs, "0x%lx = ALLOC(%lu) [id=%d]\n", + (Ulong) bp->p, bp->s, id); +#endif + if(!bp->p) + testcase_failed(tcs, "ALLOC(%lu) failed [id=%d])\n", bp->s, id); + memset((void *) bp->p, id, (size_t) bp->s); + } + else { + unsigned char *p = (unsigned char *) REALLOC(a, bp->p, bp->as[bp->i]); +#ifdef PRINT_ALLOC_OPS + testcase_printf(tcs, "0x%lx = REALLOC(0x%lx, %lu) [id=%d]\n", + (Ulong) p, (Ulong) bp->p, bp->as[bp->i], id); +#endif + if(!p) { + testcase_failed(tcs, "REALLOC(0x%lx, %lu) failed [id=%d]\n", + (Ulong) bp->p, bp->as[bp->i], id); + } + + if(bp->s < bp->as[bp->i]) { + CHECK_BLOCK_DATA(tcs, p, bp->s, id); + memset((void *) p, id, (size_t) bp->as[bp->i]); + } + else + CHECK_BLOCK_DATA(tcs, p, bp->as[bp->i], id); + + bp->s = bp->as[bp->i]; + bp->p = p; + } + + bp->i++; +} + +char * +testcase_name(void) +{ + return "realloc_copy"; +} + +void +testcase_run(TestCaseState_t *tcs) +{ + int i, j; + char sbct_buf[20]; + char *argv[] = {"-tmmsbc", "5000", "-tsbct", &sbct_buf[0], NULL}; + Allctr_t *a; + + sprintf(sbct_buf, "%d", SBC_THRESHOLD/1024); + + a = START_ALC("realloc_copy_", 0, argv); + ASSERT(tcs, a); + tcs->extra = (void *) a; + + for(i = 0; i < NO_OF_ALLOC_OPS_PER_BLOCK; i++) + for(j = 0; j < NO_OF_BLOCKS; j++) + alloc_op(tcs, a, &blocks[j], j + 1, 0); + + for(j = 0; j < NO_OF_BLOCKS; j++) + alloc_op(tcs, a, &blocks[j], j + 1, 1); + + STOP_ALC((Allctr_t *) tcs->extra); + tcs->extra = NULL; +} + +void +testcase_cleanup(TestCaseState_t *tcs) +{ + if (tcs->extra) + STOP_ALC((Allctr_t *) tcs->extra); +} + diff --git a/erts/emulator/test/alloc_SUITE_data/testcase_driver.c b/erts/emulator/test/alloc_SUITE_data/testcase_driver.c new file mode 100644 index 0000000000..1e98844838 --- /dev/null +++ b/erts/emulator/test/alloc_SUITE_data/testcase_driver.c @@ -0,0 +1,260 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <setjmp.h> +#include <string.h> + +#ifdef __WIN32__ +#undef HAVE_VSNPRINTF +#define HAVE_VSNPRINTF 1 +#define vsnprintf _vsnprintf +#endif + +#ifndef HAVE_VSNPRINTF +#define HAVE_VSNPRINTF 0 +#endif + +#define COMMENT_BUF_SZ 4096 + +#define TESTCASE_FAILED 0 +#define TESTCASE_SKIPPED 1 +#define TESTCASE_SUCCEEDED 2 + +typedef struct { + TestCaseState_t visible; + ErlDrvPort port; + int result; + jmp_buf done_jmp_buf; + char *comment; + char comment_buf[COMMENT_BUF_SZ]; +} InternalTestCaseState_t; + +ErlDrvData testcase_drv_start(ErlDrvPort port, char *command); +void testcase_drv_stop(ErlDrvData drv_data); +void testcase_drv_run(ErlDrvData drv_data, char *buf, int len); + +static ErlDrvEntry testcase_drv_entry = { + NULL, + testcase_drv_start, + testcase_drv_stop, + testcase_drv_run +}; + + +DRIVER_INIT(testcase_drv) +{ + testcase_drv_entry.driver_name = testcase_name(); + return &testcase_drv_entry; +} + +ErlDrvData +testcase_drv_start(ErlDrvPort port, char *command) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) + driver_alloc(sizeof(InternalTestCaseState_t)); + if (!itcs) { + return ERL_DRV_ERROR_GENERAL; + } + + itcs->visible.testcase_name = testcase_name(); + itcs->visible.extra = NULL; + itcs->port = port; + itcs->result = TESTCASE_FAILED; + itcs->comment = ""; + + return (ErlDrvData) itcs; +} + +void +testcase_drv_stop(ErlDrvData drv_data) +{ + testcase_cleanup((TestCaseState_t *) drv_data); + driver_free((void *) drv_data); +} + +void +testcase_drv_run(ErlDrvData drv_data, char *buf, int len) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) drv_data; + ErlDrvTermData result_atom; + ErlDrvTermData msg[12]; + + itcs->visible.command = buf; + itcs->visible.command_len = len; + + if (setjmp(itcs->done_jmp_buf) == 0) { + testcase_run((TestCaseState_t *) itcs); + itcs->result = TESTCASE_SUCCEEDED; + } + + switch (itcs->result) { + case TESTCASE_SUCCEEDED: + result_atom = driver_mk_atom("succeeded"); + break; + case TESTCASE_SKIPPED: + result_atom = driver_mk_atom("skipped"); + break; + case TESTCASE_FAILED: + default: + result_atom = driver_mk_atom("failed"); + break; + } + + msg[0] = ERL_DRV_ATOM; + msg[1] = (ErlDrvTermData) result_atom; + + msg[2] = ERL_DRV_PORT; + msg[3] = driver_mk_port(itcs->port); + + msg[4] = ERL_DRV_ATOM; + msg[5] = driver_mk_atom(itcs->visible.testcase_name); + + msg[6] = ERL_DRV_STRING; + msg[7] = (ErlDrvTermData) itcs->comment; + msg[8] = (ErlDrvTermData) strlen(itcs->comment); + + msg[9] = ERL_DRV_TUPLE; + msg[10] = (ErlDrvTermData) 4; + + driver_output_term(itcs->port, msg, 11); +} + +int +testcase_assertion_failed(TestCaseState_t *tcs, + char *file, int line, char *assertion) +{ + testcase_failed(tcs, "%s:%d: Assertion failed: \"%s\"", + file, line, assertion); + return 0; +} + +void +testcase_printf(TestCaseState_t *tcs, char *frmt, ...) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; + ErlDrvTermData msg[12]; + va_list va; + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); +#else + vsprintf(itcs->comment_buf, frmt, va); +#endif + va_end(va); + + msg[0] = ERL_DRV_ATOM; + msg[1] = (ErlDrvTermData) driver_mk_atom("print"); + + msg[2] = ERL_DRV_PORT; + msg[3] = driver_mk_port(itcs->port); + + msg[4] = ERL_DRV_ATOM; + msg[5] = driver_mk_atom(itcs->visible.testcase_name); + + msg[6] = ERL_DRV_STRING; + msg[7] = (ErlDrvTermData) itcs->comment_buf; + msg[8] = (ErlDrvTermData) strlen(itcs->comment_buf); + + msg[9] = ERL_DRV_TUPLE; + msg[10] = (ErlDrvTermData) 4; + + driver_output_term(itcs->port, msg, 11); +} + + +void testcase_succeeded(TestCaseState_t *tcs, char *frmt, ...) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; + va_list va; + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); +#else + vsprintf(itcs->comment_buf, frmt, va); +#endif + va_end(va); + + itcs->result = TESTCASE_SUCCEEDED; + itcs->comment = itcs->comment_buf; + + longjmp(itcs->done_jmp_buf, 1); +} + +void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; + va_list va; + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); +#else + vsprintf(itcs->comment_buf, frmt, va); +#endif + va_end(va); + + itcs->result = TESTCASE_SKIPPED; + itcs->comment = itcs->comment_buf; + + longjmp(itcs->done_jmp_buf, 1); +} + +void testcase_failed(TestCaseState_t *tcs, char *frmt, ...) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; + char buf[10]; + size_t bufsz = sizeof(buf); + va_list va; + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); +#else + vsprintf(itcs->comment_buf, frmt, va); +#endif + va_end(va); + + itcs->result = TESTCASE_FAILED; + itcs->comment = itcs->comment_buf; + + if (erl_drv_getenv("ERL_ABORT_ON_FAILURE", buf, &bufsz) == 0 + && strcmp("true", buf) == 0) { + fprintf(stderr, "Testcase \"%s\" failed: %s\n", + itcs->visible.testcase_name, itcs->comment); + abort(); + } + + longjmp(itcs->done_jmp_buf, 1); +} + +void *testcase_alloc(size_t size) +{ + return driver_alloc(size); +} + +void *testcase_realloc(void *ptr, size_t size) +{ + return driver_realloc(ptr, size); +} + +void testcase_free(void *ptr) +{ + driver_free(ptr); +} diff --git a/erts/emulator/test/alloc_SUITE_data/testcase_driver.h b/erts/emulator/test/alloc_SUITE_data/testcase_driver.h new file mode 100644 index 0000000000..66d567cb44 --- /dev/null +++ b/erts/emulator/test/alloc_SUITE_data/testcase_driver.h @@ -0,0 +1,51 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#ifndef TESTCASE_DRIVER_H__ +#define TESTCASE_DRIVER_H__ + +#include "erl_driver.h" +#include <stdlib.h> + +typedef struct { + char *testcase_name; + char *command; + int command_len; + void *extra; +} TestCaseState_t; + +#define ASSERT(TCS, B) \ + ((void) ((B) ? 1 : testcase_assertion_failed((TCS), __FILE__, __LINE__, #B))) + + +void testcase_printf(TestCaseState_t *tcs, char *frmt, ...); +void testcase_succeeded(TestCaseState_t *tcs, char *frmt, ...); +void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...); +void testcase_failed(TestCaseState_t *tcs, char *frmt, ...); +int testcase_assertion_failed(TestCaseState_t *tcs, char *file, int line, + char *assertion); +void *testcase_alloc(size_t size); +void *testcase_realloc(void *ptr, size_t size); +void testcase_free(void *ptr); + + +char *testcase_name(void); +void testcase_run(TestCaseState_t *tcs); +void testcase_cleanup(TestCaseState_t *tcs); + +#endif diff --git a/erts/emulator/test/alloc_SUITE_data/threads.c b/erts/emulator/test/alloc_SUITE_data/threads.c new file mode 100644 index 0000000000..1247e5d7dd --- /dev/null +++ b/erts/emulator/test/alloc_SUITE_data/threads.c @@ -0,0 +1,447 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + + +#ifndef __WIN32__ +#include <sys/types.h> +#include <unistd.h> +#include <errno.h> +#endif +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include "testcase_driver.h" +#include "allocator_test.h" + +#ifdef __WIN32__ +#undef HAVE_VSNPRINTF +#define HAVE_VSNPRINTF 1 +#define vsnprintf _vsnprintf +#endif + +#ifndef HAVE_VSNPRINTF +#define HAVE_VSNPRINTF 0 +#endif + +#define NO_OF_ALLOC_SEQS 6 +#define NO_OF_THREADS (18) +#define NO_OF_BLOCKS 10 +#define NO_OF_OPS_PER_BL 200 +#define SBC_THRESHOLD 8192 + +#define BLOCK_ID(TN, BN) ((TN) << 4 | (BN)) + +#define ERR_BUF_SZ 4096 +static char err_buf[ERR_BUF_SZ]; +static volatile int tc_failed; +static int dead_thread_no; +static erts_mutex tc_mutex; +static erts_cond tc_cond; + +static void exit_thread(int t_no, int do_lock) +{ + if (do_lock) + THR_MTX_LOCK(tc_mutex); + + while (dead_thread_no >= 0) + THR_COND_WAIT(tc_cond, tc_mutex); + dead_thread_no = t_no; + + THR_COND_BCAST(tc_cond); + THR_MTX_UNLOCK(tc_mutex); + THR_EXIT(NULL); +} + +static void fail(int t_no, char *frmt, ...) +{ + char buf[10]; + size_t bufsz = sizeof(buf); + va_list va; + + THR_MTX_LOCK(tc_mutex); + + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(err_buf, ERR_BUF_SZ, frmt, va); +#else + vsprintf(err_buf, frmt, va); +#endif + va_end(va); + + tc_failed = 1; + + if (erl_drv_getenv("ERL_ABORT_ON_FAILURE", buf, &bufsz) == 0 + && strcmp("true", buf) == 0) { + fprintf(stderr, "Testcase \"%s\" failed: %s\n", + testcase_name(), err_buf); + abort(); + } + + exit_thread(t_no, 0); +} + +static Allctr_t *alloc_not_ts = NULL; +static Allctr_t *alloc_ts_1 = NULL; +static Allctr_t *alloc_ts_2 = NULL; + +static void stop_allocators(void) +{ + if (alloc_not_ts) { + STOP_ALC(alloc_not_ts); + alloc_not_ts = NULL; + } + if (alloc_ts_1) { + STOP_ALC(alloc_ts_1); + alloc_ts_1 = NULL; + } + if (alloc_ts_2) { + STOP_ALC(alloc_ts_2); + alloc_ts_2 = NULL; + } +} + + +void *thread_func(void *arg); + +typedef struct { + Allctr_t *a; + int t_no; + int no_ops_per_bl; +} ThreadData; + + +char * +testcase_name(void) +{ + return "threads"; +} + +void +testcase_cleanup(TestCaseState_t *tcs) +{ + stop_allocators(); +} + +void +testcase_run(TestCaseState_t *tcs) +{ + struct { + erts_thread tid; + ThreadData arg; + } threads[NO_OF_THREADS+1] = {{0}}; + int no_threads; + int i; + char sbct_buf[10]; + char *argv_org[] = {"-tasaobf", "-tmmsbc5000", "-tmmmbc5000", "-tsbct", + &sbct_buf[0], NULL}; + char *argv[sizeof(argv_org)/sizeof(argv_org[0])]; + + if (!IS_THREADS_ENABLED) + testcase_skipped(tcs, "Threads not enabled"); + + alloc_not_ts = NULL; + alloc_ts_1 = NULL; + alloc_ts_2 = NULL; + + err_buf[0] = '\0'; + + sprintf(sbct_buf, "%d", SBC_THRESHOLD/1024); + + memcpy((void *) argv, argv_org, sizeof(argv_org)); + alloc_not_ts = START_ALC("threads_not_ts", 0, argv); + ASSERT(tcs, alloc_not_ts); + memcpy((void *) argv, argv_org, sizeof(argv_org)); + alloc_ts_1 = START_ALC("threads_ts_1", 1, argv); + ASSERT(tcs, alloc_ts_1); + memcpy((void *) argv, argv_org, sizeof(argv_org)); + alloc_ts_2 = START_ALC("threads_ts_2", 1, argv); + ASSERT(tcs, alloc_ts_2); + + ASSERT(tcs, !IS_ALLOC_THREAD_SAFE(alloc_not_ts)); + ASSERT(tcs, IS_ALLOC_THREAD_SAFE(alloc_ts_1)); + ASSERT(tcs, IS_ALLOC_THREAD_SAFE(alloc_ts_2)); + + tc_mutex = THR_MTX_CREATE(); + tc_cond = THR_COND_CREATE(); + + THR_MTX_LOCK(tc_mutex); + + dead_thread_no = -1; + no_threads = 0; + + for(i = 1; i <= NO_OF_THREADS; i++) { + char *alc; + int res; + + threads[i].arg.no_ops_per_bl = NO_OF_OPS_PER_BL; + + if (i == 1) { + alc = "threads_not_ts"; + threads[i].arg.no_ops_per_bl *= 2; + threads[i].arg.a = alloc_not_ts; + } + else if (i % 2 == 0) { + alc = "threads_ts_1"; + threads[i].arg.a = alloc_ts_1; + } + else { + alc = "threads_ts_2"; + threads[i].arg.a = alloc_ts_2; + } + threads[i].arg.t_no = i; + + threads[i].tid = THR_CREATE(thread_func, (void *) &threads[i].arg); + if (threads[i].tid) { + testcase_printf(tcs, "Successfully created thread %d " + "using %s_alloc\n", i, alc); + no_threads++; + } + else { + tc_failed = 1; + sprintf(err_buf, "Failed to create thread %d\n", i); + break; + } + + } + + while (no_threads) { + THR_COND_WAIT(tc_cond, tc_mutex); + if (dead_thread_no >= 0) { + no_threads--; + THR_JOIN(threads[dead_thread_no].tid); + testcase_printf(tcs, "Thread %d died\n", dead_thread_no); + dead_thread_no = -1; + THR_COND_BCAST(tc_cond); + } + } + + THR_MTX_UNLOCK(tc_mutex); + THR_MTX_DESTROY(tc_mutex); + THR_COND_DESTROY(tc_cond); + + stop_allocators(); + + if (tc_failed) + testcase_failed(tcs, "%s", err_buf); +} + +Ulong alloc_seq_1[] = { + 17, + SBC_THRESHOLD*2, + SBC_THRESHOLD*20, + SBC_THRESHOLD*2, + 17, + 0 +}; + +Ulong alloc_seq_2[] = { + SBC_THRESHOLD*20, + SBC_THRESHOLD*2, + 17, + SBC_THRESHOLD*2, + SBC_THRESHOLD*20, + 0 +}; + +Ulong alloc_seq_3[] = { + 1, + SBC_THRESHOLD/10, + SBC_THRESHOLD/9, + SBC_THRESHOLD/8, + SBC_THRESHOLD/7, + SBC_THRESHOLD/6, + SBC_THRESHOLD/5, + SBC_THRESHOLD/4, + SBC_THRESHOLD/3, + SBC_THRESHOLD/2, + SBC_THRESHOLD/1, + SBC_THRESHOLD*1, + SBC_THRESHOLD*2, + SBC_THRESHOLD*3, + SBC_THRESHOLD*4, + SBC_THRESHOLD*5, + SBC_THRESHOLD*6, + SBC_THRESHOLD*7, + SBC_THRESHOLD*8, + SBC_THRESHOLD*9, + SBC_THRESHOLD*10, + SBC_THRESHOLD*9, + SBC_THRESHOLD*8, + SBC_THRESHOLD*7, + SBC_THRESHOLD*6, + SBC_THRESHOLD*5, + SBC_THRESHOLD*4, + SBC_THRESHOLD*3, + SBC_THRESHOLD*2, + SBC_THRESHOLD*1, + SBC_THRESHOLD/2, + SBC_THRESHOLD/3, + SBC_THRESHOLD/4, + SBC_THRESHOLD/5, + SBC_THRESHOLD/6, + SBC_THRESHOLD/7, + SBC_THRESHOLD/8, + SBC_THRESHOLD/9, + SBC_THRESHOLD/10, + 1, + 0 +}; + +Ulong alloc_seq_4[] = { + SBC_THRESHOLD*2, + SBC_THRESHOLD*3, + SBC_THRESHOLD*7, + SBC_THRESHOLD*8, + SBC_THRESHOLD*5, + SBC_THRESHOLD*6, + SBC_THRESHOLD*1, + SBC_THRESHOLD*10, + SBC_THRESHOLD*4, + SBC_THRESHOLD*2, + 0 +}; + +Ulong alloc_seq_5[] = { + SBC_THRESHOLD/2, + SBC_THRESHOLD/3, + SBC_THRESHOLD/7, + SBC_THRESHOLD/8, + SBC_THRESHOLD/5, + SBC_THRESHOLD/6, + SBC_THRESHOLD/1, + SBC_THRESHOLD/10, + SBC_THRESHOLD/4, + SBC_THRESHOLD/2, + SBC_THRESHOLD/3, + SBC_THRESHOLD/7, + SBC_THRESHOLD/8, + SBC_THRESHOLD/5, + SBC_THRESHOLD/6, + SBC_THRESHOLD/1, + SBC_THRESHOLD/10, + SBC_THRESHOLD/4, + SBC_THRESHOLD/2, + 0 +}; + +Ulong alloc_seq_6[] = { + 1, 50, 100, 50, 23, 46, 2345, 23, 54, 2, 0 +}; + +Ulong *alloc_seqs[NO_OF_ALLOC_SEQS] = { + alloc_seq_1, + alloc_seq_2, + alloc_seq_3, + alloc_seq_4, + alloc_seq_5, + alloc_seq_6 +}; + +typedef struct { + unsigned char *p; + Ulong s; + int i; + Ulong *as; +} block; + +#define CHECK_BLOCK_DATA(T, P, S, D) \ + check_block_data(__FILE__, __LINE__, (T), (P), (S), (D)) + +static void +check_block_data(char *file, int line, int t_no, + unsigned char *p, Ulong sz, int d) +{ + Ulong i; + for (i = 0; i < sz; i++) + if (p[i] != (unsigned char) d) + fail(t_no, "%s:%d: Thread no %d found clobbered data! " + "found id=%d; expected id=%d\n", + file, line, t_no, (int) p[i], d); +} + +static void +alloc_op(int t_no, Allctr_t *a, block *bp, int id, int clean_up) +{ + if (tc_failed) + exit_thread(t_no, 1); + + if(bp->p) + CHECK_BLOCK_DATA(t_no, bp->p, bp->s, id); + + if(bp->as[bp->i] == 0 || clean_up) { + FREE(a, bp->p); + bp->p = NULL; + bp->s = 0; + bp->i = 0; /* start from the beginning again */ + return; + } + + if(!bp->p) { + bp->s = bp->as[bp->i]; + bp->p = (unsigned char *) ALLOC(a, bp->s); + if(!bp->p) + fail(t_no, "ALLOC(%lu) failed [id=%d])\n", bp->s, id); + memset((void *) bp->p, id, (size_t) bp->s); + } + else { + unsigned char *p = (unsigned char *) REALLOC(a, bp->p, bp->as[bp->i]); + if(!p) + fail(t_no, "REALLOC(0x%lx, %lu) failed [id=%d]\n", + (Ulong) bp->p, bp->as[bp->i], id); + + if(bp->s < bp->as[bp->i]) { + CHECK_BLOCK_DATA(t_no, p, bp->s, id); + memset((void *) p, id, (size_t) bp->as[bp->i]); + } + else + CHECK_BLOCK_DATA(t_no, p, bp->as[bp->i], id); + + bp->s = bp->as[bp->i]; + bp->p = p; + } + + bp->i++; +} + + +void * +thread_func(void *arg) +{ + int i, j; + ThreadData *td = ((ThreadData *) arg); + block bs[NO_OF_BLOCKS]; + + for(i = 0; i < NO_OF_BLOCKS; i++) { + bs[i].p = NULL; + bs[i].s = 0; + bs[i].i = 0; + bs[i].as = alloc_seqs[i % NO_OF_ALLOC_SEQS]; + } + + for(i = 0; i < td->no_ops_per_bl; i++) { + + for(j = 0; j < NO_OF_BLOCKS; j++) + alloc_op(td->t_no, td->a, &bs[j], BLOCK_ID(td->t_no, j), 0); + } + + for(j = 0; j < NO_OF_BLOCKS; j++) + alloc_op(td->t_no, td->a, &bs[j], BLOCK_ID(td->t_no, j), 1); + + exit_thread(td->t_no, 1); + return NULL; +} diff --git a/erts/emulator/test/beam_SUITE.erl b/erts/emulator/test/beam_SUITE.erl new file mode 100644 index 0000000000..cc1626630b --- /dev/null +++ b/erts/emulator/test/beam_SUITE.erl @@ -0,0 +1,281 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(beam_SUITE). + +-export([all/1, packed_registers/1, apply_last/1, apply_last_bif/1, + buildo_mucho/1, heap_sizes/1, big_lists/1]). + +-export([applied/2]). + +-include("test_server.hrl"). + +all(suite) -> + [packed_registers, apply_last, apply_last_bif, buildo_mucho, + heap_sizes, big_lists]. + + +%% Verify that apply(M, F, A) is really tail recursive. +apply_last(Config) when is_list(Config) -> + Pid=spawn(?MODULE, applied, [self(), 10000]), + Size = + receive + {Pid, finished} -> + stack_size(Pid) + after 30000 -> + ?t:fail("applied/2 timed out.") + end, + Pid ! die, + ?t:format("Size: ~p~n", [Size]), + if + Size < 700 -> + ok; + true -> + ?t:fail("10000 apply() grew stack too much.") + end, + ok. + +stack_size(Pid) -> + {heap_size, HS}=process_info(Pid, heap_size), + {stack_size,SS}=process_info(Pid, stack_size), + HS+SS. + +applied(Starter, 0) -> + Starter ! {self(), finished}, + receive + die -> + ok + end, + ok; +applied(Starter, N) -> + apply(?MODULE, applied, [Starter, N-1]). + +%% Verify that tail-recursive use of apply(M,F,A) on a Bif works." +apply_last_bif(Config) when is_list(Config) -> + apply(erlang, abs, [1]). + +%% Test three high register numbers in a put_list instruction +%% (to test whether packing works properly). +packed_registers(Config) when is_list(Config) -> + ?line PrivDir = ?config(priv_dir, Config), + ?line Mod = packed_regs, + ?line Name = filename:join(PrivDir, atom_to_list(Mod) ++ ".erl"), + + %% Generate a module which generates a list of tuples. + %% put_list(A) -> [{A, 600}, {A, 999}, ... {A, 0}]. + ?line Code = gen_packed_regs(600, ["-module("++atom_to_list(Mod)++").\n", + "-export([put_list/1]).\n", + "put_list(A) ->\n["]), + ?line ok = file:write_file(Name, Code), + + %% Compile the module. + ?line io:format("Compiling: ~s\n", [Name]), + ?line CompRc = compile:file(Name, [{outdir, PrivDir}, report]), + ?line io:format("Result: ~p\n",[CompRc]), + ?line {ok, Mod} = CompRc, + + %% Load it. + ?line io:format("Loading...\n",[]), + ?line LoadRc = code:load_abs(filename:join(PrivDir, atom_to_list(Mod))), + ?line {module,_Module} = LoadRc, + + %% Call it and verify result. + ?line Term = {a, b}, + ?line L = Mod:put_list(Term), + ?line verify_packed_regs(L, Term, 600), + ok. + +gen_packed_regs(0, Acc) -> + [Acc|"{A,0}].\n"]; +gen_packed_regs(N, Acc) -> + gen_packed_regs(N-1, [Acc,"{A,",integer_to_list(N)|"},\n"]). + +verify_packed_regs([], _, -1) -> ok; +verify_packed_regs([{Term, N}| T], Term, N) -> + verify_packed_regs(T, Term, N-1); +verify_packed_regs(L, Term, N) -> + ?line ok = io:format("Expected [{~p, ~p}|T]; got\n~p\n", [Term, N, L]), + ?line test_server:fail(). + +buildo_mucho(Config) when is_list(Config) -> + ?line buildo_mucho_1(), + ok. + +buildo_mucho_1() -> + %% Thanks to Per Gustafsson, HiPE. + [{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}, + {<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1},{<<>>,1}]. + +heap_sizes(Config) when is_list(Config) -> + ?line Sizes = erlang:system_info(heap_sizes), + ?line io:format("~p heap sizes\n", [length(Sizes)]), + ?line io:format("~p\n", [Sizes]), + + %% Verify that heap sizes increase monotonically. + ?line Largest = lists:foldl(fun(E, P) when is_integer(P), E > P -> E; + (E, []) -> E + end, [], Sizes), + + %% Verify that the largest heap size consists of 31 or 63 bits. + ?line + case Largest bsr (erlang:system_info(wordsize)*8-2) of + R when R > 0 -> ok + end, + ok. + +%% Thanks to Igor Goryachev. + +big_lists(Config) when is_list(Config) -> + b(), + ok. + +a() -> + {selected, + ["uid", + "nickname", + "n_family", + "n_given", + "email_pref", + "tel_home_number", + "tel_cellular_number", + "adr_home_country", + "adr_home_locality", + "adr_home_region", + "url", + "gender", + "bday", + "constitution", + "height", + "weight", + "hair", + "routine", + "smoke", + "maritalstatus", + "children", + "independence", + "school_number", + "school_locality", + "school_title", + "school_period", + "org_orgname", + "title", + "adr_work_locality", + "photo_type", + "photo_binval"], + [{"test"}]}. + +b() -> + case a() of + {selected, + ["uid", + "nickname", + "n_family", + "n_given", + "email_pref", + "tel_home_number", + "tel_cellular_number", + "adr_home_country", + "adr_home_locality", + "adr_home_region", + "url", + "gender", + "bday", + "constitution", + "height", + "weight", + "hair", + "routine", + "smoke", + "maritalstatus", + "children", + "independence", + "school_number", + "school_locality", + "school_title", + "school_period", + "org_orgname", + "title", + "adr_work_locality", + "photo_type", + "photo_binval"], + _} -> + ok + end. diff --git a/erts/emulator/test/beam_literals_SUITE.erl b/erts/emulator/test/beam_literals_SUITE.erl new file mode 100644 index 0000000000..75841adbfc --- /dev/null +++ b/erts/emulator/test/beam_literals_SUITE.erl @@ -0,0 +1,433 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(beam_literals_SUITE). +-export([all/1]). +-export([putting/1, matching_smalls/1, matching_smalls_jt/1, + matching_bigs/1, matching_more_bigs/1, + matching_bigs_and_smalls/1, badmatch/1, case_clause/1, + receiving/1, literal_type_tests/1, + put_list/1, fconv/1, literal_case_expression/1]). + +-include("test_server.hrl"). + +all(suite) -> + [putting, matching_smalls, matching_smalls_jt, + matching_bigs, matching_more_bigs, + matching_bigs_and_smalls, badmatch, case_clause, + receiving, literal_type_tests, + put_list, fconv, literal_case_expression]. + +putting(doc) -> "Test creating lists and tuples containing big number literals."; +putting(Config) when is_list(Config) -> + -773973888575883407313908 = chksum(putting1(8987697898797)). + +putting1(X) -> + {8797987987987987872256443, [1324483773773], {3.1415, 2.71, [2.5, 35.125|9.31]}, + [X|349873987387373], + [329878349873|-387394729872], -773973937933873929749873}. + +matching_bigs(doc) -> "Test matching of a few big number literals (in Beam," + "select_val/3 will NOT be used)."; +matching_bigs(Config) when is_list(Config) -> + a = matching1(3972907842873739), + b = matching1(-389789298378939783333333333333333333784), + other = matching1(42). + +matching_smalls(doc) -> "Test matching small numbers (both positive and negative)."; +matching_smalls(Config) when is_list(Config) -> + ?line a = m_small(-42), + ?line b = m_small(0), + ?line c = m_small(105), + ?line d = m_small(-13), + ?line e = m_small(337848), + ?line other = m_small(324), + ?line other = m_small(-7), + ok. + +m_small(-42) -> a; +m_small(0) -> b; +m_small(105) -> c; +m_small(-13) -> d; +m_small(337848) -> e; +m_small(_) -> other. + +matching_smalls_jt(doc) -> + "Test matching small numbers (both positive and negative). " + "Make sure that a jump table is used."; +matching_smalls_jt(Config) when is_list(Config) -> + ?line a = m_small_jt(-2), + ?line b = m_small_jt(-1), + ?line c = m_small_jt(0), + ?line d = m_small_jt(2), + ?line e = m_small_jt(3), + ?line other = m_small(324), + ?line other = m_small(-7), + ok. + +m_small_jt(-2) -> a; +m_small_jt(-1) -> b; +m_small_jt(0) -> c; +m_small_jt(2) -> d; +m_small_jt(3) -> e; +m_small_jt(_) -> other. + +%% Big numbers, no select_val. + +matching1(3972907842873739) -> a; +matching1(-389789298378939783333333333333333333784) -> b; +matching1(_) -> other. + + +matching_more_bigs(doc) -> "Test matching of a big number literals (in Beam," + "a select_val/3 instruction will be used)."; +matching_more_bigs(Config) when is_list(Config) -> + a = matching2(-999766349740978337), + b = matching2(9734097866575478), + c = matching2(-966394677364879734), + d = matching2(13987294872948990), + e = matching2(777723896192459245), + other = matching2(7), + other = matching2(39789827988888888888888888888347474444444444444444444). + +%% Big numbers with select_val. + +matching2(-999766349740978337) -> a; +matching2(9734097866575478) -> b; +matching2(-966394677364879734) -> c; +matching2(13987294872948990) -> d; +matching2(777723896192459245) -> e; +matching2(_) -> other. + +matching_bigs_and_smalls(doc) -> "Test matching of a mix of big numbers and literals."; +matching_bigs_and_smalls(suite) -> []; +matching_bigs_and_smalls(Config) when is_list(Config) -> + a = matching3(38472928723987239873873), + b = matching3(0), + c = matching3(-3873973932710954671207461057614287561348756348743634876436784367873), + d = matching3(3978429867297393873), + e = matching3(42), + f = matching3(-4533), + other = matching3(77), + other = matching3(39274120984379249874219748). + +%% Mixed small and big. + +matching3(38472928723987239873873) -> a; +matching3(0) -> b; +matching3(-3873973932710954671207461057614287561348756348743634876436784367873) -> c; +matching3(3978429867297393873) -> d; +matching3(42) -> e; +matching3(-4533) -> f; +matching3(_) -> other. + +badmatch(doc) -> "Test literal badmatches with big number and floats."; +badmatch(Config) when is_list(Config) -> + %% We are satisfied if we can load this module and run it. + Big = id(32984798729847892498297824872982972978239874), + Float = id(3.1415927), + ?line catch a = Big, + ?line catch b = Float, + ?line {'EXIT',{{badmatch,3879373498378993387},_}} = + (catch c = 3879373498378993387), + ?line {'EXIT',{{badmatch,7.0},_}} = (catch d = 7.0), + ?line case Big of + Big -> ok + end, + ?line case Float of + Float -> ok + end, + ok. + +case_clause(Config) when is_list(Config) -> + ?line {'EXIT',{{case_clause,337.0},_}} = (catch case_clause_float()), + ?line {'EXIT',{{try_clause,42.0},_}} = (catch try_case_clause_float()), + ?line {'EXIT',{{case_clause,37932749837839747383847398743789348734987},_}} = + (catch case_clause_big()), + ?line {'EXIT',{{try_clause,977387349872349870423364354398566348},_}} = + (catch try_case_clause_big()), + ok. + +case_clause_float() -> + case 337.0 of + blurf -> ok + end. + +try_case_clause_float() -> + try 42.0 of + blurf -> ok + catch _:_ -> + error + end. + +case_clause_big() -> + case 37932749837839747383847398743789348734987 of + blurf -> ok + end. + +try_case_clause_big() -> + try 977387349872349870423364354398566348 of + blurf -> ok + catch _:_ -> + error + end. + +receiving(doc) -> "Test receive with a big number literal (more than 27 bits, " + "less than 32 bits)."; +receiving(Config) when is_list(Config) -> + Self = self(), + spawn(fun() -> Self ! here_is_a_message end), + ok = receive + here_is_a_message -> + ok + after 16#f1234567 -> + timeout + end. + +literal_type_tests(doc) -> "Test type tests on literal values."; +literal_type_tests(Config) when is_list(Config) -> + %% Generate an Erlang module with all different type of type tests. + ?line Tests = make_test([{T, L} || T <- type_tests(), L <- literals()]), + ?line Mod = literal_test, + ?line Func = {function, 0, test, 0, [{clause,0,[],[],Tests}]}, + ?line Form = [{attribute,0,module,Mod}, + {attribute,0,compile,export_all}, + Func, {eof,0}], + + %% Print generated code for inspection. + ?line lists:foreach(fun (F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Form), + + %% Test compile:form/1. This implies full optimization (default). + ?line {ok,Mod,Code1} = compile:forms(Form), + ?line {module,Mod} = code:load_binary(Mod, Mod, Code1), + ?line Mod:test(), + ?line true = code:delete(Mod), + ?line code:purge(Mod), + + %% Test compile:form/2. Turn off all optimizations. + ?line {ok,Mod,Code2} = compile:forms(Form, [binary,report,time, + no_copt,no_postopt]), + ?line {module,Mod} = code:load_binary(Mod, Mod, Code2), + ?line Mod:test(), + ?line true = code:delete(Mod), + ?line code:purge(Mod), + ok. + +make_test([{is_function=T,L}|Ts]) -> + [test(T, L),test(T, 0, L)|make_test(Ts)]; +make_test([{T,L}|Ts]) -> + [test(T, L)|make_test(Ts)]; +make_test([]) -> []. + +test(T, L) -> + S = lists:flatten(io_lib:format("begin io:format(\"~~p~~n\", [{~p,~p}]), if ~w(~w) -> true; true -> false end end. ", [T, L, T, L])), + {ok,Toks,_Line} = erl_scan:string(S), + {ok,E} = erl_parse:parse_exprs(Toks), + {value,Val,_Bs} = erl_eval:exprs(E, []), + {match,0,{atom,0,Val},hd(E)}. + +test(T, A, L) -> + S = lists:flatten(io_lib:format("begin io:format(\"~~p~~n\", [{~p,~p,~p}]), if ~w(~w, ~w) -> true; true -> false end end. ", + [T,L,A,T,L,A])), + {ok,Toks,_Line} = erl_scan:string(S), + {ok,E} = erl_parse:parse_exprs(Toks), + {value,Val,_Bs} = erl_eval:exprs(E, []), + {match,0,{atom,0,Val},hd(E)}. + +literals() -> + [42, + 3.14, + -3, + 32982724987789283473473838474, + [], + xxxx]. + +type_tests() -> + [is_boolean, + is_integer, + is_float, + is_number, + is_atom, + is_list, + is_tuple, + is_pid, + is_reference, + is_port, + is_binary, + is_function]. + +put_list(Config) when is_list(Config) -> + %% put_list x0 Literal Reg + ?line [Config|8739757395764] = put_list_rqr(Config), + ?line {[Config|7779757395764],Config} = put_list_rqx(Config), + ?line [Config|98765432100000] = put_list_rqy(Config), + + %% put_list x Literal Reg + ?line [Config|16#FFFFF77777137483769] = put_list_xqr(ignore, Config), + ?line {[Config|16#AAAAAFFFFF77777],{a,b},Config} = put_list_xqx({a,b}, Config), + ?line [Config|12777765432979879] = put_list_xqy(ignore, Config), + + %% put_list y Literal Reg + ?line [Config|17424134793676869867] = put_list_yqr(Config), + ?line {[Config|77424134793676869867],Config} = put_list_yqx(Config), + ?line {Config,[Config|16#BCDEFF4241676869867]} = put_list_yqy(Config), + + %% put_list Literal x0 Reg + ?line [42.0|Config] = put_list_qrr(Config), + ?line [Config,42.0|Config] = put_list_qrx(Config), + ?line [100.0|Config] = put_list_qry(Config), + + %% put_list Literal x1 Reg + ?line [127.0|Config] = put_list_qxr({ignore,me}, Config), + ?line [Config,130.0|Config] = put_list_qxx(ignore, Config), + ?line [99.0|Config] = put_list_qxy(Config), + + %% put_list Literal y0 Reg + ?line [200.0|Config] = put_list_qyr(Config), + ?line [Config,210.0|Config] = put_list_qyx(Config), + ?line [[300.0|Config]|Config] = put_list_qyy(Config), + + ok. + +%% put_list x0 Literal x0 +put_list_rqr(Config) -> [Config|8739757395764]. + +%% put_list x0 Literal x1 +put_list_rqx(Config) -> {[Config|7779757395764],Config}. + +%% put_list x0 Literal y0 +put_list_rqy(Config) -> + Res = [Config|98765432100000], + id(42), + Res. + +%% put_list x1 Literal x0 +put_list_xqr(_, Config) -> [Config|16#FFFFF77777137483769]. + +%% put_list x1 Literal x2 +put_list_xqx(A, Config) -> {[Config|16#AAAAAFFFFF77777],A,Config}. + +%% put_list x1 Literal y0 +put_list_xqy(_, Config) -> + Res = [Config|12777765432979879], + id(42), + Res. + +%% put_list y0 Literal x0 +put_list_yqr(Config) -> + id(Config), + [Config|17424134793676869867]. + +%% put_list y0 Literal x1 +put_list_yqx(Config) -> + id(Config), + {[Config|77424134793676869867],Config}. + +%% put_list y1 Literal y0 +put_list_yqy(Config) -> + id(Config), + Res = [Config|16#BCDEFF4241676869867], + id(Config), + {Config,Res}. + +%% put_list Literal x0 x0 +put_list_qrr(Config) -> + [42.0|Config]. + +%% put_list Literal x0 x1 +put_list_qrx(Config) -> + [Config,42.0|Config]. + +%% put_list Literal x0 y0 +put_list_qry(Config) -> + Res = [100.0|Config], + id(0), + Res. + +%% put_list Literal x1 x0 +put_list_qxr(_, Config) -> + [127.0|Config]. + +%% put_list Literal x1 x2 +put_list_qxx(_, Config) -> + [Config,130.0|Config]. + +%% put_list Literal x1 y0 +put_list_qxy(Config) -> + Res = [99.0|Config], + id(0), + Res. + +%% put_list Literal y0 x0 +put_list_qyr(Config) -> + id(Config), + [200.0|Config]. + +%% put_list Literal y0 x1 +put_list_qyx(Config) -> + id(Config), + [Config,210.0|Config]. + +%% put_list Literal y1 y0 +put_list_qyy(Config) -> + id(Config), + Res = [300.0|Config], + id(Config), + [Res|Config]. + +fconv(Config) when is_list(Config) -> + ?line 5.0 = fconv_1(-34444444450.0), + ?line 13.0 = fconv_2(7.0), + ok. + +fconv_1(F) when is_float(F) -> + 34444444455 + F. + +fconv_2(F) when is_float(F) -> + 6.0 + F. + +literal_case_expression(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line Src = filename:join(DataDir, "literal_case_expression"), + ?line {ok,literal_case_expression=Mod,Code} = compile:file(Src, [from_asm,binary]), + ?line {module,Mod} = code:load_binary(Mod, Src, Code), + ?line ok = Mod:x(), + ?line ok = Mod:y(), + ?line true = code:delete(Mod), + ?line code:purge(Mod), + ok. + +%% Help functions. + +chksum(Term) -> + chksum(Term, 0). + +chksum([List|T], Sum) when is_list(List) -> + chksum(T, chksum(List, Sum)); +chksum([H|T], Sum) -> + chksum(T, chksum(H, Sum)); +chksum([], Sum) -> Sum; +chksum(Tuple, Sum) when is_tuple(Tuple) -> + chksum(tuple_to_list(Tuple), Sum); +chksum(Int, Sum) when is_integer(Int) -> + Sum * 5 + Int; +chksum(Other, Sum) -> + erlang:phash2([Other|Sum], 39729747). + +id(I) -> I. diff --git a/erts/emulator/test/beam_literals_SUITE_data/literal_case_expression.S b/erts/emulator/test/beam_literals_SUITE_data/literal_case_expression.S new file mode 100644 index 0000000000..c0ffe9ab53 --- /dev/null +++ b/erts/emulator/test/beam_literals_SUITE_data/literal_case_expression.S @@ -0,0 +1,70 @@ +{module, literal_case_expression}. %% version = 0 + +{exports, [{module_info,0},{module_info,1},{x,0},{y,0}]}. + +{attributes, []}. + +{labels, 15}. + + +{function, x, 0, 2}. + {label,1}. + {func_info,{atom,literal_case_expression},{atom,x},0}. + {label,2}. + {test,is_integer,{f,5},[{integer,343434343434}]}. + {select_val,{integer,343434343434}, + {f,5}, + {list,[{integer,343434343434}, + {f,3}, + {integer,397439}, + {f,4}, + {integer,3976554567454}, + {f,4}]}}. + {label,3}. + {move,{atom,ok},{x,0}}. + return. + {label,4}. + {move,{atom,error},{x,0}}. + return. + {label,5}. + {case_end,{integer,343434343434}}. + + +{function, y, 0, 7}. + {label,6}. + {func_info,{atom,literal_case_expression},{atom,y},0}. + {label,7}. + {test,is_float,{f,10},[{float,34.0000}]}. + {select_val,{float,34.0000}, + {f,10}, + {list,[{float,34.0000}, + {f,8}, + {float,397.655}, + {f,9}, + {float,39.7439}, + {f,9}]}}. + {label,8}. + {move,{atom,ok},{x,0}}. + return. + {label,9}. + {move,{atom,error},{x,0}}. + return. + {label,10}. + {case_end,{float,34.0000}}. + + +{function, module_info, 0, 12}. + {label,11}. + {func_info,{atom,literal_case_expression},{atom,module_info},0}. + {label,12}. + {move,{atom,literal_case_expression},{x,0}}. + {call_ext_only,1,{extfunc,erlang,get_module_info,1}}. + + +{function, module_info, 1, 14}. + {label,13}. + {func_info,{atom,literal_case_expression},{atom,module_info},1}. + {label,14}. + {move,{x,0},{x,1}}. + {move,{atom,literal_case_expression},{x,0}}. + {call_ext_only,2,{extfunc,erlang,get_module_info,2}}. diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl new file mode 100644 index 0000000000..cfbc5dfe81 --- /dev/null +++ b/erts/emulator/test/bif_SUITE.erl @@ -0,0 +1,317 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(bif_SUITE). + +-include("test_server.hrl"). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + t_list_to_existing_atom/1,os_env/1,otp_7526/1, + binary_to_atom/1,binary_to_existing_atom/1, + atom_to_binary/1,min_max/1]). + +all(suite) -> + [t_list_to_existing_atom,os_env,otp_7526, + atom_to_binary,binary_to_atom,binary_to_existing_atom, + min_max]. + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog=?t:timetrap(?t:minutes(1)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +t_list_to_existing_atom(Config) when is_list(Config) -> + ?line all = list_to_existing_atom("all"), + ?line ?MODULE = list_to_existing_atom(?MODULE_STRING), + ?line UnlikelyStr = "dsfj923874390867er869fds9864y97jhg3973qerueoru", + try + ?line list_to_existing_atom(UnlikelyStr), + ?line ?t:fail() + catch + error:badarg -> ok + end, + + %% The compiler has become smarter! We need the call to id/1 in + %% the next line. + ?line UnlikelyAtom = list_to_atom(id(UnlikelyStr)), + ?line UnlikelyAtom = list_to_existing_atom(UnlikelyStr), + ok. + +os_env(doc) -> + []; +os_env(suite) -> + []; +os_env(Config) when is_list(Config) -> + ?line EnvVar1 = "MjhgvFDrresdCghN mnjkUYg vfrD", + ?line false = os:getenv(EnvVar1), + ?line true = os:putenv(EnvVar1, "mors"), + ?line "mors" = os:getenv(EnvVar1), + ?line true = os:putenv(EnvVar1, ""), + ?line case os:getenv(EnvVar1) of + "" -> ?line ok; + false -> ?line ok; + BadVal -> ?line ?t:fail(BadVal) + end, + %% os:putenv and os:getenv currently uses a temp buf of size 1024 + %% for storing key+value + ?line os_env_long(1010, 1030, "hej hopp"). + +os_env_long(Min, Max, _Value) when Min > Max -> + ?line ok; +os_env_long(Min, Max, Value) -> + ?line EnvVar = lists:duplicate(Min, $X), + ?line true = os:putenv(EnvVar, Value), + ?line Value = os:getenv(EnvVar), + ?line true = os:putenv(EnvVar, ""), + ?line os_env_long(Min+1, Max, Value). + +otp_7526(doc) -> + ["Test that string:to_integer does not Halloc in wrong order."]; +otp_7526(Config) when is_list(Config) -> + ok = test_7526(256). + +iterate_7526(0, Acc) -> Acc; +iterate_7526(N, Acc) -> + iterate_7526(N - 1, + [case string:to_integer("9223372036854775808,\n") of + {Int, _Foo} -> Int + end | Acc]). + +do_test_7526(N,M) -> + {Self, Ref} = {self(), make_ref()}, + T = erlang:make_tuple(M,0), + spawn_opt(fun()-> + L = iterate_7526(N, []), + BadList = [X || X <- L, X =/= 9223372036854775808], + BadLen = length(BadList), + M = length(tuple_to_list(T)), + %%io:format("~b bad conversions: ~p~n", [BadLen, BadList]), + Self ! {done, Ref, BadLen} + end, + [link,{fullsweep_after,0}]), + receive {done, Ref, Len} -> Len end. + + +test_7526(0) -> + ok; +test_7526(N) -> + case do_test_7526(1000,N) of + 0 -> test_7526(N-1); + Other -> + {error,N,Other} + end. + +-define(BADARG(E), {'EXIT',{badarg,_}} = (catch E)). +-define(SYS_LIMIT(E), {'EXIT',{system_limit,_}} = (catch E)). + +binary_to_atom(Config) when is_list(Config) -> + HalfLong = lists:seq(0, 127), + HalfLongAtom = list_to_atom(HalfLong), + HalfLongBin = list_to_binary(HalfLong), + Long = lists:seq(0, 254), + LongAtom = list_to_atom(Long), + LongBin = list_to_binary(Long), + + %% latin1 + ?line '' = test_binary_to_atom(<<>>, latin1), + ?line '\377' = test_binary_to_atom(<<255>>, latin1), + ?line HalfLongAtom = test_binary_to_atom(HalfLongBin, latin1), + ?line LongAtom = test_binary_to_atom(LongBin, latin1), + + %% utf8 + ?line '' = test_binary_to_atom(<<>>, utf8), + ?line HalfLongAtom = test_binary_to_atom(HalfLongBin, utf8), + ?line HalfLongAtom = test_binary_to_atom(HalfLongBin, unicode), + ?line [] = [C || C <- lists:seq(128, 255), + begin + list_to_atom([C]) =/= + test_binary_to_atom(<<C/utf8>>, utf8) + end], + + %% badarg failures. + ?line fail_binary_to_atom(atom), + ?line fail_binary_to_atom(42), + ?line fail_binary_to_atom({a,b,c}), + ?line fail_binary_to_atom([1,2,3]), + ?line fail_binary_to_atom([]), + ?line fail_binary_to_atom(42.0), + ?line fail_binary_to_atom(self()), + ?line fail_binary_to_atom(make_ref()), + ?line fail_binary_to_atom(<<0:7>>), + ?line fail_binary_to_atom(<<42:13>>), + ?line ?BADARG(binary_to_atom(id(<<>>), blurf)), + ?line ?BADARG(binary_to_atom(id(<<>>), [])), + + %% Bad UTF8 sequences. + ?line ?BADARG(binary_to_atom(id(<<255>>), utf8)), + ?line ?BADARG(binary_to_atom(id(<<255,0>>), utf8)), + ?line ?BADARG(binary_to_atom(id(<<0:512/unit:8,255>>), utf8)), + ?line ?BADARG(binary_to_atom(id(<<0:512/unit:8,255,0>>), utf8)), + ?line ?BADARG(binary_to_atom(id(<<16#C0,16#80>>), utf8)), %Overlong 0. + ?line [?BADARG(binary_to_atom(<<C/utf8>>, utf8)) || + C <- lists:seq(256, 16#D7FF)], + ?line [?BADARG(binary_to_atom(<<C/utf8>>, utf8)) || + C <- lists:seq(16#E000, 16#FFFD)], + ?line [?BADARG(binary_to_atom(<<C/utf8>>, utf8)) || + C <- lists:seq(16#10000, 16#8FFFF)], + ?line [?BADARG(binary_to_atom(<<C/utf8>>, utf8)) || + C <- lists:seq(16#90000, 16#10FFFF)], + + %% system_limit failures. + ?line ?SYS_LIMIT(binary_to_atom(<<0:256/unit:8>>, latin1)), + ?line ?SYS_LIMIT(binary_to_atom(<<0:257/unit:8>>, latin1)), + ?line ?SYS_LIMIT(binary_to_atom(<<0:512/unit:8>>, latin1)), + ?line ?SYS_LIMIT(binary_to_atom(<<0:256/unit:8>>, utf8)), + ?line ?SYS_LIMIT(binary_to_atom(<<0:257/unit:8>>, utf8)), + ?line ?SYS_LIMIT(binary_to_atom(<<0:512/unit:8>>, utf8)), + ok. + +test_binary_to_atom(Bin0, Encoding) -> + Res = binary_to_atom(Bin0, Encoding), + Res = binary_to_existing_atom(Bin0, Encoding), + Bin1 = id(<<7:3,Bin0/binary,32:5>>), + Sz = byte_size(Bin0), + <<_:3,UnalignedBin:Sz/binary,_:5>> = Bin1, + Res = binary_to_atom(UnalignedBin, Encoding). + +fail_binary_to_atom(Bin) -> + try + binary_to_atom(Bin, latin1) + catch + error:badarg -> + ok + end, + try + binary_to_atom(Bin, utf8) + catch + error:badarg -> + ok + end, + try + binary_to_existing_atom(Bin, latin1) + catch + error:badarg -> + ok + end, + try + binary_to_existing_atom(Bin, utf8) + catch + error:badarg -> + ok + end. + + +binary_to_existing_atom(Config) when is_list(Config) -> + ?line UnlikelyBin = <<"ou0897979655678dsfj923874390867er869fds973qerueoru">>, + try + ?line binary_to_existing_atom(UnlikelyBin, latin1), + ?line ?t:fail() + catch + error:badarg -> ok + end, + + try + ?line binary_to_existing_atom(UnlikelyBin, utf8), + ?line ?t:fail() + catch + error:badarg -> ok + end, + + ?line UnlikelyAtom = binary_to_atom(id(UnlikelyBin), latin1), + ?line UnlikelyAtom = binary_to_existing_atom(UnlikelyBin, latin1), + ok. + + +atom_to_binary(Config) when is_list(Config) -> + HalfLong = lists:seq(0, 127), + HalfLongAtom = list_to_atom(HalfLong), + HalfLongBin = list_to_binary(HalfLong), + Long = lists:seq(0, 254), + LongAtom = list_to_atom(Long), + LongBin = list_to_binary(Long), + + %% latin1 + ?line <<>> = atom_to_binary('', latin1), + ?line <<"abc">> = atom_to_binary(abc, latin1), + ?line <<127>> = atom_to_binary('\177', latin1), + ?line HalfLongBin = atom_to_binary(HalfLongAtom, latin1), + ?line LongBin = atom_to_binary(LongAtom, latin1), + + %% utf8. + ?line <<>> = atom_to_binary('', utf8), + ?line <<>> = atom_to_binary('', unicode), + ?line <<127>> = atom_to_binary('\177', utf8), + ?line <<"abcdef">> = atom_to_binary(abcdef, utf8), + ?line HalfLongBin = atom_to_binary(HalfLongAtom, utf8), + ?line LongAtomBin = atom_to_binary(LongAtom, utf8), + ?line verify_long_atom_bin(LongAtomBin, 0), + + %% Failing cases. + ?line fail_atom_to_binary(<<1>>), + ?line fail_atom_to_binary(42), + ?line fail_atom_to_binary({a,b,c}), + ?line fail_atom_to_binary([1,2,3]), + ?line fail_atom_to_binary([]), + ?line fail_atom_to_binary(42.0), + ?line fail_atom_to_binary(self()), + ?line fail_atom_to_binary(make_ref()), + ?line ?BADARG(atom_to_binary(id(a), blurf)), + ?line ?BADARG(atom_to_binary(id(b), [])), + ok. + +verify_long_atom_bin(<<I/utf8,T/binary>>, I) -> + verify_long_atom_bin(T, I+1); +verify_long_atom_bin(<<>>, 255) -> ok. + +fail_atom_to_binary(Term) -> + try + atom_to_binary(Term, latin1) + catch + error:badarg -> + ok + end, + try + atom_to_binary(Term, utf8) + catch + error:badarg -> + ok + end. + +min_max(Config) when is_list(Config) -> + ?line a = erlang:min(id(a), a), + ?line a = erlang:min(id(a), b), + ?line a = erlang:min(id(b), a), + ?line b = erlang:min(id(b), b), + ?line a = erlang:max(id(a), a), + ?line b = erlang:max(id(a), b), + ?line b = erlang:max(id(b), a), + ?line b = erlang:max(id(b), b), + + ?line 42.0 = erlang:min(42.0, 42), + ?line 42.0 = erlang:max(42.0, 42), + + ok. + +%% Helpers + +id(I) -> I. + diff --git a/erts/emulator/test/big_SUITE.erl b/erts/emulator/test/big_SUITE.erl new file mode 100644 index 0000000000..6cedd39009 --- /dev/null +++ b/erts/emulator/test/big_SUITE.erl @@ -0,0 +1,396 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(big_SUITE). + + +-export([all/1]). +-export([t_div/1, eq_28/1, eq_32/1, eq_big/1, eq_math/1, big_literals/1, + borders/1, negative/1, big_float/1, big_float_1/1, big_float_2/1, + shift_limit_1/1, powmod/1, system_limit/1, otp_6692/1]). + +%% Internal exports. +-export([eval/1, funcall/2]). +-export([init/3]). + +-export([fac/1, fib/1, pow/2, gcd/2, lcm/2]). + +-export([init_per_testcase/2, fin_per_testcase/2]). + +-include("test_server.hrl"). + +all(suite) -> + [t_div, eq_28, eq_32, eq_big, eq_math, big_literals, borders, + negative, big_float, shift_limit_1, powmod, system_limit, otp_6692]. + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog=?t:timetrap(?t:minutes(3)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +%% +%% Syntax of data files: +%% Expr1 = Expr2. +%% ... +%% built in functions are: +%% fac(N). +%% fib(N). +%% pow(X, N) == X ^ N +%% gcd(Q, R) +%% lcm(Q, R) +%% +eq_28(Config) when is_list(Config) -> + TestFile = test_file(Config, "eq_28.dat"), + test(TestFile). + +eq_32(Config) when is_list(Config) -> + TestFile = test_file(Config, "eq_32.dat"), + test(TestFile). + +eq_big(Config) when is_list(Config) -> + TestFile = test_file(Config, "eq_big.dat"), + test(TestFile). + +eq_math(Config) when is_list(Config) -> + TestFile = test_file(Config, "eq_math.dat"), + test(TestFile). + + +borders(doc) -> "Tests border cases between small/big."; +borders(Config) when is_list(Config) -> + TestFile = test_file(Config, "borders.dat"), + test(TestFile). + +negative(Config) when is_list(Config) -> + TestFile = test_file(Config, "negative.dat"), + test(TestFile). + + +%% Find test file +test_file(Config, Name) -> + DataDir = ?config(data_dir, Config), + filename:join(DataDir, Name). + +%% +%% +%% Run test on file test_big_seq.erl +%% +%% +test(File) -> + test(File, [node()]). + +test(File, Nodes) -> + ?line {ok,Fd} = file:open(File, [read]), + Res = test(File, Fd, Nodes), + file:close(Fd), + case Res of + {0,Cases} -> {comment, integer_to_list(Cases) ++ " cases"}; + {_,_} -> test_server:fail() + end. + +test(File, Fd, Ns) -> + test(File, Fd, Ns, 0, 0, 0). + +test(File, Fd, Ns, L, Cases, Err) -> + case io:parse_erl_exprs(Fd, '') of + {eof,_} -> {Err, Cases}; + {error, {Line,_Mod,Message}, _} -> + Fmt = erl_parse:format_error(Message), + io:format("~s:~w: error ~s~n", [File, Line+L, Fmt]), + {Err+1, Cases}; + {ok, [{match,ThisLine,Expr1,Expr2}], Line} -> + case multi_match(Ns, {op,0,'-',Expr1,Expr2}) of + [] -> + test(File, Fd, Ns, Line+L-1,Cases+1, Err); + [_|_] -> + PP = erl_pp:expr({op,0,'=/=',Expr1,Expr2}), + io:format("~s:~w : error ~s~n", [File,ThisLine+L, PP]), + test(File, Fd, Ns, Line+L-1,Cases+1, Err+1) + end; + {ok, Exprs, Line} -> + PP = erl_pp:exprs(Exprs), + io:format("~s: ~w: equation expected not ~s~n", [File,Line+L,PP]), + test(File, Fd, Ns, Line+L-1,Cases+1, Err+1) + end. + +multi_match(Ns, Expr) -> + multi_match(Ns, Expr, []). + +multi_match([Node|Ns], Expr, Rs) -> + ?line X = rpc:call(Node, big_SUITE, eval, [Expr]), + if X == 0 -> multi_match(Ns, Expr, Rs); + true -> multi_match(Ns, Expr, [{Node,X}|Rs]) + end; +multi_match([], _, Rs) -> Rs. + +eval(Expr) -> + Fun = {?MODULE,funcall}, + {value,V,_} = erl_eval:expr(Expr, [], Fun), %Applied arithmetic BIFs. + V = eval(Expr, Fun), %Real arithmetic instructions. + V. + +funcall(F, As) -> apply(?MODULE, F, As). + +%% Like a subset of erl_eval:expr/3, but uses real arithmetic instructions instead of +%% applying them (it does make a difference). + +eval({op,_,Op,A0}, LFH) -> + A = eval(A0, LFH), + Res = eval_op(Op, A), + erlang:garbage_collect(), + Res; +eval({op,_,Op,A0,B0}, LFH) -> + [A,B] = eval_list([A0,B0], LFH), + Res = eval_op(Op, A, B), + erlang:garbage_collect(), + Res; +eval({integer,_,I}, _) -> I; +eval({call,_,{atom,_,Local},Args0}, LFH) -> + Args = eval_list(Args0, LFH), + LFH(Local, Args). + +eval_list([E|Es], LFH) -> + [eval(E, LFH)|eval_list(Es, LFH)]; +eval_list([], _) -> []. + +eval_op('-', A) -> -A; +eval_op('+', A) -> +A; +eval_op('bnot', A) -> bnot A. + +eval_op('-', A, B) -> A - B; +eval_op('+', A, B) -> A + B; +eval_op('*', A, B) -> A * B; +eval_op('div', A, B) -> A div B; +eval_op('rem', A, B) -> A rem B; +eval_op('band', A, B) -> A band B; +eval_op('bor', A, B) -> A bor B; +eval_op('bxor', A, B) -> A bxor B; +eval_op('bsl', A, B) -> A bsl B; +eval_op('bsr', A, B) -> A bsr B. + +%% Built in test functions + +fac(0) -> 1; +fac(1) -> 1; +fac(N) -> N * fac(N-1). + +%% +%% X ^ N +%% +pow(_, 0) -> 1; +pow(X, 1) -> X; +pow(X, N) when (N band 1) == 1 -> + X2 = pow(X, N bsr 1), + X*X2*X2; +pow(X, N) -> + X2 = pow(X, N bsr 1), + X2*X2. + +fib(0) -> 1; +fib(1) -> 1; +fib(N) -> fib(N-1) + fib(N-2). + +%% +%% Gcd +%% +gcd(Q, 0) -> Q; +gcd(Q, R) -> gcd(R, Q rem R). + +%% +%% Least common multiple +%% +lcm(Q, R) -> + Q*R div gcd(Q, R). + + +%% Test case t_div cut in from R2D test suite. + +t_div(Config) when is_list(Config) -> + ?line 'try'(fun() -> 98765432101234 div 98765432101235 end, 0), + + % Big remainder, small quotient. + ?line 'try'(fun() -> 339254531512 div 68719476736 end, 4), + ok. + +'try'(Fun, Result) -> + 'try'(89, Fun, Result, []). + +'try'(0, _, _, _) -> + ok; +'try'(Iter, Fun, Result, Filler) -> + spawn(?MODULE, init, [self(), Fun, list_to_tuple(Filler)]), + receive + {result, Result} -> + 'try'(Iter-1, Fun, Result, [0|Filler]); + {result, Other} -> + io:format("Expected ~p; got ~p~n", [Result, Other]), + test_server:fail() + end. + +init(ReplyTo, Fun, _Filler) -> + ReplyTo ! {result, Fun()}. + +big_literals(doc) -> + "Tests that big-number literals work correctly."; +big_literals(Config) when is_list(Config) -> + %% Note: The literal test cannot be compiler on a pre-R4 Beam emulator, + %% so we compile it now. + ?line DataDir = ?config(data_dir, Config), + ?line Test = filename:join(DataDir, "literal_test"), + ?line {ok, Mod, Bin} = compile:file(Test, [binary]), + ?line {module, Mod} = code:load_binary(Mod, Mod, Bin), + ?line ok = Mod:t(), + ok. + +big_float(doc) -> + ["Test cases for mixing bignums and floats"]; +big_float(suite) -> + [big_float_1, big_float_2]. + +big_float_1(doc) -> + ["OTP-2436, part 1"]; +big_float_1(Config) when is_list(Config) -> + %% F is a number very close to a maximum float. + ?line F = id(1.7e308), + ?line I = trunc(F), + ?line true = (I == F), + ?line false = (I /= F), + ?line true = (I > F/2), + ?line false = (I =< F/2), + ?line true = (I*2 >= F), + ?line false = (I*2 < F), + ?line true = (I*I > F), + ?line false = (I*I =< F), + + ?line true = (F == I), + ?line false = (F /= I), + ?line false = (F/2 > I), + ?line true = (F/2 =< I), + ?line false = (F >= I*2), + ?line true = (F < I*2), + ?line false = (F > I*I), + ?line true = (F =< I*I), + ok. + +big_float_2(doc) -> + ["OTP-2436, part 2"]; +big_float_2(Config) when is_list(Config) -> + ?line F = id(1.7e308), + ?line I = trunc(F), + ?line {'EXIT', _} = (catch 1/(2*I)), + ?line _Ignore = 2/I, + ?line {'EXIT', _} = (catch 4/(2*I)), + ok. + +shift_limit_1(doc) -> + ["OTP-3256"]; +shift_limit_1(Config) when is_list(Config) -> + ?line case catch (id(1) bsl 100000000) of + {'EXIT', {system_limit, _}} -> + ok + end, + ok. + +powmod(Config) when is_list(Config) -> + A = 1696192905348584855517250509684275447603964214606878827319923580493120589769459602596313014087329389174229999430092223701630077631205171572331191216670754029016160388576759960413039261647653627052707047, + B = 43581177444506616087519351724629421082877485633442736512567383077022781906420535744195118099822189576169114064491200598595995538299156626345938812352676950427869649947439032133573270227067833308153431095, + C = 52751775381034251994634567029696659541685100826881826508158083211003576763074162948462801435204697796532659535818017760528684167216110865807581759669824808936751316879636014972704885388116861127856231, + 42092892863788727404752752803608028634538446791189806757622214958680350350975318060071308251566643822307995215323107194784213893808887471095918905937046217646432382915847269148913963434734284563536888 = powmod(A, B, C), + ok. + +powmod(A, 1, C) -> + A rem C; +powmod(A, 2, C) -> + A*A rem C; +powmod(A, B, C) -> + B1 = B div 2, + B2 = B - B1, + P = powmod(A, B1, C), + case B2 of + B1 -> + (P*P) rem C; + _ -> + (P*P*A) rem C + end. + +system_limit(Config) when is_list(Config) -> + ?line Maxbig = maxbig(), + ?line {'EXIT',{system_limit,_}} = (catch Maxbig+1), + ?line {'EXIT',{system_limit,_}} = (catch -Maxbig-1), + ?line {'EXIT',{system_limit,_}} = (catch 2*Maxbig), + ?line {'EXIT',{system_limit,_}} = (catch bnot Maxbig), + ?line {'EXIT',{system_limit,_}} = (catch apply(erlang, id('bnot'), [Maxbig])), + ?line {'EXIT',{system_limit,_}} = (catch Maxbig bsl 2), + ?line {'EXIT',{system_limit,_}} = (catch apply(erlang, id('bsl'), [Maxbig,2])), + ?line {'EXIT',{system_limit,_}} = (catch id(1) bsl (1 bsl 45)), + ?line {'EXIT',{system_limit,_}} = (catch id(1) bsl (1 bsl 69)), + ok. + +maxbig() -> + %% We assume that the maximum arity is (1 bsl 19) - 1. + Ws = erlang:system_info(wordsize), + (((1 bsl ((16777184 * (Ws div 4))-1)) - 1) bsl 1) + 1. + +id(I) -> I. + +otp_6692(suite) -> + []; +otp_6692(doc) -> + ["Tests for DIV/REM bug reported in OTP-6692"]; +otp_6692(Config) when is_list(Config)-> + ?line loop1(1,1000). + +fact(N) -> + fact(N,1). + +fact(0,P) -> P; +fact(N,P) -> fact(N-1,P*N). + +raised(X,1) -> + X; +raised(X,N) -> + X*raised(X,N-1). + +loop1(M,M) -> + ok; +loop1(N,M) -> + loop2(fact(N),raised(7,7),1,8), + loop1(N+1,M). + +loop2(_,_,M,M) -> + ok; +loop2(X,Y,N,M) -> + Z = raised(Y,N), + case X rem Z of + Z -> + exit({failed,X,'REM',Z,'=',Z}); + 0 -> + case (X div Z) * Z of + X -> + ok; + Wrong -> + exit({failed,X,'DIV',Z,'*',Z,'=',Wrong}) + end; + _ -> + ok + end, + loop2(X,Y,N+1,M). + diff --git a/erts/emulator/test/big_SUITE_data/borders.dat b/erts/emulator/test/big_SUITE_data/borders.dat new file mode 100644 index 0000000000..52e4f35861 --- /dev/null +++ b/erts/emulator/test/big_SUITE_data/borders.dat @@ -0,0 +1,1116 @@ +33554427 = 33554429 + (-2). +-33554433 = -33554435 - (-2). +33554428 = 33554429 + (-1). +-33554434 = -33554435 - (-1). +33554429 = 33554429 + 0. +-33554435 = -33554435 - 0. +33554430 = 33554429 + 1. +-33554436 = -33554435 - 1. +33554431 = 33554429 + 2. +-33554437 = -33554435 - 2. +33554432 = 33554429 + 3. +-33554438 = -33554435 - 3. +33554433 = 33554429 + 4. +-33554439 = -33554435 - 4. +33554434 = 33554429 + 5. +-33554440 = -33554435 - 5. +33554435 = 33554429 + 6. +-33554441 = -33554435 - 6. +33554428 = 33554430 + (-2). +-33554432 = -33554434 - (-2). +33554429 = 33554430 + (-1). +-33554433 = -33554434 - (-1). +33554430 = 33554430 + 0. +-33554434 = -33554434 - 0. +33554431 = 33554430 + 1. +-33554435 = -33554434 - 1. +33554432 = 33554430 + 2. +-33554436 = -33554434 - 2. +33554433 = 33554430 + 3. +-33554437 = -33554434 - 3. +33554434 = 33554430 + 4. +-33554438 = -33554434 - 4. +33554435 = 33554430 + 5. +-33554439 = -33554434 - 5. +33554436 = 33554430 + 6. +-33554440 = -33554434 - 6. +33554429 = 33554431 + (-2). +-33554431 = -33554433 - (-2). +33554430 = 33554431 + (-1). +-33554432 = -33554433 - (-1). +33554431 = 33554431 + 0. +-33554433 = -33554433 - 0. +33554432 = 33554431 + 1. +-33554434 = -33554433 - 1. +33554433 = 33554431 + 2. +-33554435 = -33554433 - 2. +33554434 = 33554431 + 3. +-33554436 = -33554433 - 3. +33554435 = 33554431 + 4. +-33554437 = -33554433 - 4. +33554436 = 33554431 + 5. +-33554438 = -33554433 - 5. +33554437 = 33554431 + 6. +-33554439 = -33554433 - 6. +33554430 = 33554432 + (-2). +-33554430 = -33554432 - (-2). +33554431 = 33554432 + (-1). +-33554431 = -33554432 - (-1). +33554432 = 33554432 + 0. +-33554432 = -33554432 - 0. +33554433 = 33554432 + 1. +-33554433 = -33554432 - 1. +33554434 = 33554432 + 2. +-33554434 = -33554432 - 2. +33554435 = 33554432 + 3. +-33554435 = -33554432 - 3. +33554436 = 33554432 + 4. +-33554436 = -33554432 - 4. +33554437 = 33554432 + 5. +-33554437 = -33554432 - 5. +33554438 = 33554432 + 6. +-33554438 = -33554432 - 6. +33554431 = 33554433 + (-2). +-33554429 = -33554431 - (-2). +33554432 = 33554433 + (-1). +-33554430 = -33554431 - (-1). +33554433 = 33554433 + 0. +-33554431 = -33554431 - 0. +33554434 = 33554433 + 1. +-33554432 = -33554431 - 1. +33554435 = 33554433 + 2. +-33554433 = -33554431 - 2. +33554436 = 33554433 + 3. +-33554434 = -33554431 - 3. +33554437 = 33554433 + 4. +-33554435 = -33554431 - 4. +33554438 = 33554433 + 5. +-33554436 = -33554431 - 5. +33554439 = 33554433 + 6. +-33554437 = -33554431 - 6. +33554432 = 33554434 + (-2). +-33554428 = -33554430 - (-2). +33554433 = 33554434 + (-1). +-33554429 = -33554430 - (-1). +33554434 = 33554434 + 0. +-33554430 = -33554430 - 0. +33554435 = 33554434 + 1. +-33554431 = -33554430 - 1. +33554436 = 33554434 + 2. +-33554432 = -33554430 - 2. +33554437 = 33554434 + 3. +-33554433 = -33554430 - 3. +33554438 = 33554434 + 4. +-33554434 = -33554430 - 4. +33554439 = 33554434 + 5. +-33554435 = -33554430 - 5. +33554440 = 33554434 + 6. +-33554436 = -33554430 - 6. +33554432 = 33554430 - (-2). +-33554432 = -33554430 + (-2). +33554431 = 33554430 - (-1). +-33554431 = -33554430 + (-1). +33554430 = 33554430 - 0. +-33554430 = -33554430 + 0. +33554429 = 33554430 - 1. +-33554429 = -33554430 + 1. +33554428 = 33554430 - 2. +-33554428 = -33554430 + 2. +33554427 = 33554430 - 3. +-33554427 = -33554430 + 3. +33554426 = 33554430 - 4. +-33554426 = -33554430 + 4. +33554425 = 33554430 - 5. +-33554425 = -33554430 + 5. +33554424 = 33554430 - 6. +-33554424 = -33554430 + 6. +33554433 = 33554431 - (-2). +-33554433 = -33554431 + (-2). +33554432 = 33554431 - (-1). +-33554432 = -33554431 + (-1). +33554431 = 33554431 - 0. +-33554431 = -33554431 + 0. +33554430 = 33554431 - 1. +-33554430 = -33554431 + 1. +33554429 = 33554431 - 2. +-33554429 = -33554431 + 2. +33554428 = 33554431 - 3. +-33554428 = -33554431 + 3. +33554427 = 33554431 - 4. +-33554427 = -33554431 + 4. +33554426 = 33554431 - 5. +-33554426 = -33554431 + 5. +33554425 = 33554431 - 6. +-33554425 = -33554431 + 6. +33554434 = 33554432 - (-2). +-33554434 = -33554432 + (-2). +33554433 = 33554432 - (-1). +-33554433 = -33554432 + (-1). +33554432 = 33554432 - 0. +-33554432 = -33554432 + 0. +33554431 = 33554432 - 1. +-33554431 = -33554432 + 1. +33554430 = 33554432 - 2. +-33554430 = -33554432 + 2. +33554429 = 33554432 - 3. +-33554429 = -33554432 + 3. +33554428 = 33554432 - 4. +-33554428 = -33554432 + 4. +33554427 = 33554432 - 5. +-33554427 = -33554432 + 5. +33554426 = 33554432 - 6. +-33554426 = -33554432 + 6. +33554435 = 33554433 - (-2). +-33554435 = -33554433 + (-2). +33554434 = 33554433 - (-1). +-33554434 = -33554433 + (-1). +33554433 = 33554433 - 0. +-33554433 = -33554433 + 0. +33554432 = 33554433 - 1. +-33554432 = -33554433 + 1. +33554431 = 33554433 - 2. +-33554431 = -33554433 + 2. +33554430 = 33554433 - 3. +-33554430 = -33554433 + 3. +33554429 = 33554433 - 4. +-33554429 = -33554433 + 4. +33554428 = 33554433 - 5. +-33554428 = -33554433 + 5. +33554427 = 33554433 - 6. +-33554427 = -33554433 + 6. +33554436 = 33554434 - (-2). +-33554436 = -33554434 + (-2). +33554435 = 33554434 - (-1). +-33554435 = -33554434 + (-1). +33554434 = 33554434 - 0. +-33554434 = -33554434 + 0. +33554433 = 33554434 - 1. +-33554433 = -33554434 + 1. +33554432 = 33554434 - 2. +-33554432 = -33554434 + 2. +33554431 = 33554434 - 3. +-33554431 = -33554434 + 3. +33554430 = 33554434 - 4. +-33554430 = -33554434 + 4. +33554429 = 33554434 - 5. +-33554429 = -33554434 + 5. +33554428 = 33554434 - 6. +-33554428 = -33554434 + 6. +33554437 = 33554435 - (-2). +-33554437 = -33554435 + (-2). +33554436 = 33554435 - (-1). +-33554436 = -33554435 + (-1). +33554435 = 33554435 - 0. +-33554435 = -33554435 + 0. +33554434 = 33554435 - 1. +-33554434 = -33554435 + 1. +33554433 = 33554435 - 2. +-33554433 = -33554435 + 2. +33554432 = 33554435 - 3. +-33554432 = -33554435 + 3. +33554431 = 33554435 - 4. +-33554431 = -33554435 + 4. +33554430 = 33554435 - 5. +-33554430 = -33554435 + 5. +33554429 = 33554435 - 6. +-33554429 = -33554435 + 6. +67108859 = 67108861 + (-2). +-67108865 = -67108867 - (-2). +67108860 = 67108861 + (-1). +-67108866 = -67108867 - (-1). +67108861 = 67108861 + 0. +-67108867 = -67108867 - 0. +67108862 = 67108861 + 1. +-67108868 = -67108867 - 1. +67108863 = 67108861 + 2. +-67108869 = -67108867 - 2. +67108864 = 67108861 + 3. +-67108870 = -67108867 - 3. +67108865 = 67108861 + 4. +-67108871 = -67108867 - 4. +67108866 = 67108861 + 5. +-67108872 = -67108867 - 5. +67108867 = 67108861 + 6. +-67108873 = -67108867 - 6. +67108860 = 67108862 + (-2). +-67108864 = -67108866 - (-2). +67108861 = 67108862 + (-1). +-67108865 = -67108866 - (-1). +67108862 = 67108862 + 0. +-67108866 = -67108866 - 0. +67108863 = 67108862 + 1. +-67108867 = -67108866 - 1. +67108864 = 67108862 + 2. +-67108868 = -67108866 - 2. +67108865 = 67108862 + 3. +-67108869 = -67108866 - 3. +67108866 = 67108862 + 4. +-67108870 = -67108866 - 4. +67108867 = 67108862 + 5. +-67108871 = -67108866 - 5. +67108868 = 67108862 + 6. +-67108872 = -67108866 - 6. +67108861 = 67108863 + (-2). +-67108863 = -67108865 - (-2). +67108862 = 67108863 + (-1). +-67108864 = -67108865 - (-1). +67108863 = 67108863 + 0. +-67108865 = -67108865 - 0. +67108864 = 67108863 + 1. +-67108866 = -67108865 - 1. +67108865 = 67108863 + 2. +-67108867 = -67108865 - 2. +67108866 = 67108863 + 3. +-67108868 = -67108865 - 3. +67108867 = 67108863 + 4. +-67108869 = -67108865 - 4. +67108868 = 67108863 + 5. +-67108870 = -67108865 - 5. +67108869 = 67108863 + 6. +-67108871 = -67108865 - 6. +67108862 = 67108864 + (-2). +-67108862 = -67108864 - (-2). +67108863 = 67108864 + (-1). +-67108863 = -67108864 - (-1). +67108864 = 67108864 + 0. +-67108864 = -67108864 - 0. +67108865 = 67108864 + 1. +-67108865 = -67108864 - 1. +67108866 = 67108864 + 2. +-67108866 = -67108864 - 2. +67108867 = 67108864 + 3. +-67108867 = -67108864 - 3. +67108868 = 67108864 + 4. +-67108868 = -67108864 - 4. +67108869 = 67108864 + 5. +-67108869 = -67108864 - 5. +67108870 = 67108864 + 6. +-67108870 = -67108864 - 6. +67108863 = 67108865 + (-2). +-67108861 = -67108863 - (-2). +67108864 = 67108865 + (-1). +-67108862 = -67108863 - (-1). +67108865 = 67108865 + 0. +-67108863 = -67108863 - 0. +67108866 = 67108865 + 1. +-67108864 = -67108863 - 1. +67108867 = 67108865 + 2. +-67108865 = -67108863 - 2. +67108868 = 67108865 + 3. +-67108866 = -67108863 - 3. +67108869 = 67108865 + 4. +-67108867 = -67108863 - 4. +67108870 = 67108865 + 5. +-67108868 = -67108863 - 5. +67108871 = 67108865 + 6. +-67108869 = -67108863 - 6. +67108864 = 67108866 + (-2). +-67108860 = -67108862 - (-2). +67108865 = 67108866 + (-1). +-67108861 = -67108862 - (-1). +67108866 = 67108866 + 0. +-67108862 = -67108862 - 0. +67108867 = 67108866 + 1. +-67108863 = -67108862 - 1. +67108868 = 67108866 + 2. +-67108864 = -67108862 - 2. +67108869 = 67108866 + 3. +-67108865 = -67108862 - 3. +67108870 = 67108866 + 4. +-67108866 = -67108862 - 4. +67108871 = 67108866 + 5. +-67108867 = -67108862 - 5. +67108872 = 67108866 + 6. +-67108868 = -67108862 - 6. +67108864 = 67108862 - (-2). +-67108864 = -67108862 + (-2). +67108863 = 67108862 - (-1). +-67108863 = -67108862 + (-1). +67108862 = 67108862 - 0. +-67108862 = -67108862 + 0. +67108861 = 67108862 - 1. +-67108861 = -67108862 + 1. +67108860 = 67108862 - 2. +-67108860 = -67108862 + 2. +67108859 = 67108862 - 3. +-67108859 = -67108862 + 3. +67108858 = 67108862 - 4. +-67108858 = -67108862 + 4. +67108857 = 67108862 - 5. +-67108857 = -67108862 + 5. +67108856 = 67108862 - 6. +-67108856 = -67108862 + 6. +67108865 = 67108863 - (-2). +-67108865 = -67108863 + (-2). +67108864 = 67108863 - (-1). +-67108864 = -67108863 + (-1). +67108863 = 67108863 - 0. +-67108863 = -67108863 + 0. +67108862 = 67108863 - 1. +-67108862 = -67108863 + 1. +67108861 = 67108863 - 2. +-67108861 = -67108863 + 2. +67108860 = 67108863 - 3. +-67108860 = -67108863 + 3. +67108859 = 67108863 - 4. +-67108859 = -67108863 + 4. +67108858 = 67108863 - 5. +-67108858 = -67108863 + 5. +67108857 = 67108863 - 6. +-67108857 = -67108863 + 6. +67108866 = 67108864 - (-2). +-67108866 = -67108864 + (-2). +67108865 = 67108864 - (-1). +-67108865 = -67108864 + (-1). +67108864 = 67108864 - 0. +-67108864 = -67108864 + 0. +67108863 = 67108864 - 1. +-67108863 = -67108864 + 1. +67108862 = 67108864 - 2. +-67108862 = -67108864 + 2. +67108861 = 67108864 - 3. +-67108861 = -67108864 + 3. +67108860 = 67108864 - 4. +-67108860 = -67108864 + 4. +67108859 = 67108864 - 5. +-67108859 = -67108864 + 5. +67108858 = 67108864 - 6. +-67108858 = -67108864 + 6. +67108867 = 67108865 - (-2). +-67108867 = -67108865 + (-2). +67108866 = 67108865 - (-1). +-67108866 = -67108865 + (-1). +67108865 = 67108865 - 0. +-67108865 = -67108865 + 0. +67108864 = 67108865 - 1. +-67108864 = -67108865 + 1. +67108863 = 67108865 - 2. +-67108863 = -67108865 + 2. +67108862 = 67108865 - 3. +-67108862 = -67108865 + 3. +67108861 = 67108865 - 4. +-67108861 = -67108865 + 4. +67108860 = 67108865 - 5. +-67108860 = -67108865 + 5. +67108859 = 67108865 - 6. +-67108859 = -67108865 + 6. +67108868 = 67108866 - (-2). +-67108868 = -67108866 + (-2). +67108867 = 67108866 - (-1). +-67108867 = -67108866 + (-1). +67108866 = 67108866 - 0. +-67108866 = -67108866 + 0. +67108865 = 67108866 - 1. +-67108865 = -67108866 + 1. +67108864 = 67108866 - 2. +-67108864 = -67108866 + 2. +67108863 = 67108866 - 3. +-67108863 = -67108866 + 3. +67108862 = 67108866 - 4. +-67108862 = -67108866 + 4. +67108861 = 67108866 - 5. +-67108861 = -67108866 + 5. +67108860 = 67108866 - 6. +-67108860 = -67108866 + 6. +67108869 = 67108867 - (-2). +-67108869 = -67108867 + (-2). +67108868 = 67108867 - (-1). +-67108868 = -67108867 + (-1). +67108867 = 67108867 - 0. +-67108867 = -67108867 + 0. +67108866 = 67108867 - 1. +-67108866 = -67108867 + 1. +67108865 = 67108867 - 2. +-67108865 = -67108867 + 2. +67108864 = 67108867 - 3. +-67108864 = -67108867 + 3. +67108863 = 67108867 - 4. +-67108863 = -67108867 + 4. +67108862 = 67108867 - 5. +-67108862 = -67108867 + 5. +67108861 = 67108867 - 6. +-67108861 = -67108867 + 6. +134217723 = 134217725 + (-2). +-134217729 = -134217731 - (-2). +134217724 = 134217725 + (-1). +-134217730 = -134217731 - (-1). +134217725 = 134217725 + 0. +-134217731 = -134217731 - 0. +134217726 = 134217725 + 1. +-134217732 = -134217731 - 1. +134217727 = 134217725 + 2. +-134217733 = -134217731 - 2. +134217728 = 134217725 + 3. +-134217734 = -134217731 - 3. +134217729 = 134217725 + 4. +-134217735 = -134217731 - 4. +134217730 = 134217725 + 5. +-134217736 = -134217731 - 5. +134217731 = 134217725 + 6. +-134217737 = -134217731 - 6. +134217724 = 134217726 + (-2). +-134217728 = -134217730 - (-2). +134217725 = 134217726 + (-1). +-134217729 = -134217730 - (-1). +134217726 = 134217726 + 0. +-134217730 = -134217730 - 0. +134217727 = 134217726 + 1. +-134217731 = -134217730 - 1. +134217728 = 134217726 + 2. +-134217732 = -134217730 - 2. +134217729 = 134217726 + 3. +-134217733 = -134217730 - 3. +134217730 = 134217726 + 4. +-134217734 = -134217730 - 4. +134217731 = 134217726 + 5. +-134217735 = -134217730 - 5. +134217732 = 134217726 + 6. +-134217736 = -134217730 - 6. +134217725 = 134217727 + (-2). +-134217727 = -134217729 - (-2). +134217726 = 134217727 + (-1). +-134217728 = -134217729 - (-1). +134217727 = 134217727 + 0. +-134217729 = -134217729 - 0. +134217728 = 134217727 + 1. +-134217730 = -134217729 - 1. +134217729 = 134217727 + 2. +-134217731 = -134217729 - 2. +134217730 = 134217727 + 3. +-134217732 = -134217729 - 3. +134217731 = 134217727 + 4. +-134217733 = -134217729 - 4. +134217732 = 134217727 + 5. +-134217734 = -134217729 - 5. +134217733 = 134217727 + 6. +-134217735 = -134217729 - 6. +134217726 = 134217728 + (-2). +-134217726 = -134217728 - (-2). +134217727 = 134217728 + (-1). +-134217727 = -134217728 - (-1). +134217728 = 134217728 + 0. +-134217728 = -134217728 - 0. +134217729 = 134217728 + 1. +-134217729 = -134217728 - 1. +134217730 = 134217728 + 2. +-134217730 = -134217728 - 2. +134217731 = 134217728 + 3. +-134217731 = -134217728 - 3. +134217732 = 134217728 + 4. +-134217732 = -134217728 - 4. +134217733 = 134217728 + 5. +-134217733 = -134217728 - 5. +134217734 = 134217728 + 6. +-134217734 = -134217728 - 6. +134217727 = 134217729 + (-2). +-134217725 = -134217727 - (-2). +134217728 = 134217729 + (-1). +-134217726 = -134217727 - (-1). +134217729 = 134217729 + 0. +-134217727 = -134217727 - 0. +134217730 = 134217729 + 1. +-134217728 = -134217727 - 1. +134217731 = 134217729 + 2. +-134217729 = -134217727 - 2. +134217732 = 134217729 + 3. +-134217730 = -134217727 - 3. +134217733 = 134217729 + 4. +-134217731 = -134217727 - 4. +134217734 = 134217729 + 5. +-134217732 = -134217727 - 5. +134217735 = 134217729 + 6. +-134217733 = -134217727 - 6. +134217728 = 134217730 + (-2). +-134217724 = -134217726 - (-2). +134217729 = 134217730 + (-1). +-134217725 = -134217726 - (-1). +134217730 = 134217730 + 0. +-134217726 = -134217726 - 0. +134217731 = 134217730 + 1. +-134217727 = -134217726 - 1. +134217732 = 134217730 + 2. +-134217728 = -134217726 - 2. +134217733 = 134217730 + 3. +-134217729 = -134217726 - 3. +134217734 = 134217730 + 4. +-134217730 = -134217726 - 4. +134217735 = 134217730 + 5. +-134217731 = -134217726 - 5. +134217736 = 134217730 + 6. +-134217732 = -134217726 - 6. +134217728 = 134217726 - (-2). +-134217728 = -134217726 + (-2). +134217727 = 134217726 - (-1). +-134217727 = -134217726 + (-1). +134217726 = 134217726 - 0. +-134217726 = -134217726 + 0. +134217725 = 134217726 - 1. +-134217725 = -134217726 + 1. +134217724 = 134217726 - 2. +-134217724 = -134217726 + 2. +134217723 = 134217726 - 3. +-134217723 = -134217726 + 3. +134217722 = 134217726 - 4. +-134217722 = -134217726 + 4. +134217721 = 134217726 - 5. +-134217721 = -134217726 + 5. +134217720 = 134217726 - 6. +-134217720 = -134217726 + 6. +134217729 = 134217727 - (-2). +-134217729 = -134217727 + (-2). +134217728 = 134217727 - (-1). +-134217728 = -134217727 + (-1). +134217727 = 134217727 - 0. +-134217727 = -134217727 + 0. +134217726 = 134217727 - 1. +-134217726 = -134217727 + 1. +134217725 = 134217727 - 2. +-134217725 = -134217727 + 2. +134217724 = 134217727 - 3. +-134217724 = -134217727 + 3. +134217723 = 134217727 - 4. +-134217723 = -134217727 + 4. +134217722 = 134217727 - 5. +-134217722 = -134217727 + 5. +134217721 = 134217727 - 6. +-134217721 = -134217727 + 6. +134217730 = 134217728 - (-2). +-134217730 = -134217728 + (-2). +134217729 = 134217728 - (-1). +-134217729 = -134217728 + (-1). +134217728 = 134217728 - 0. +-134217728 = -134217728 + 0. +134217727 = 134217728 - 1. +-134217727 = -134217728 + 1. +134217726 = 134217728 - 2. +-134217726 = -134217728 + 2. +134217725 = 134217728 - 3. +-134217725 = -134217728 + 3. +134217724 = 134217728 - 4. +-134217724 = -134217728 + 4. +134217723 = 134217728 - 5. +-134217723 = -134217728 + 5. +134217722 = 134217728 - 6. +-134217722 = -134217728 + 6. +134217731 = 134217729 - (-2). +-134217731 = -134217729 + (-2). +134217730 = 134217729 - (-1). +-134217730 = -134217729 + (-1). +134217729 = 134217729 - 0. +-134217729 = -134217729 + 0. +134217728 = 134217729 - 1. +-134217728 = -134217729 + 1. +134217727 = 134217729 - 2. +-134217727 = -134217729 + 2. +134217726 = 134217729 - 3. +-134217726 = -134217729 + 3. +134217725 = 134217729 - 4. +-134217725 = -134217729 + 4. +134217724 = 134217729 - 5. +-134217724 = -134217729 + 5. +134217723 = 134217729 - 6. +-134217723 = -134217729 + 6. +134217732 = 134217730 - (-2). +-134217732 = -134217730 + (-2). +134217731 = 134217730 - (-1). +-134217731 = -134217730 + (-1). +134217730 = 134217730 - 0. +-134217730 = -134217730 + 0. +134217729 = 134217730 - 1. +-134217729 = -134217730 + 1. +134217728 = 134217730 - 2. +-134217728 = -134217730 + 2. +134217727 = 134217730 - 3. +-134217727 = -134217730 + 3. +134217726 = 134217730 - 4. +-134217726 = -134217730 + 4. +134217725 = 134217730 - 5. +-134217725 = -134217730 + 5. +134217724 = 134217730 - 6. +-134217724 = -134217730 + 6. +134217733 = 134217731 - (-2). +-134217733 = -134217731 + (-2). +134217732 = 134217731 - (-1). +-134217732 = -134217731 + (-1). +134217731 = 134217731 - 0. +-134217731 = -134217731 + 0. +134217730 = 134217731 - 1. +-134217730 = -134217731 + 1. +134217729 = 134217731 - 2. +-134217729 = -134217731 + 2. +134217728 = 134217731 - 3. +-134217728 = -134217731 + 3. +134217727 = 134217731 - 4. +-134217727 = -134217731 + 4. +134217726 = 134217731 - 5. +-134217726 = -134217731 + 5. +134217725 = 134217731 - 6. +-134217725 = -134217731 + 6. +268435451 = 268435453 + (-2). +-268435457 = -268435459 - (-2). +268435452 = 268435453 + (-1). +-268435458 = -268435459 - (-1). +268435453 = 268435453 + 0. +-268435459 = -268435459 - 0. +268435454 = 268435453 + 1. +-268435460 = -268435459 - 1. +268435455 = 268435453 + 2. +-268435461 = -268435459 - 2. +268435456 = 268435453 + 3. +-268435462 = -268435459 - 3. +268435457 = 268435453 + 4. +-268435463 = -268435459 - 4. +268435458 = 268435453 + 5. +-268435464 = -268435459 - 5. +268435459 = 268435453 + 6. +-268435465 = -268435459 - 6. +268435452 = 268435454 + (-2). +-268435456 = -268435458 - (-2). +268435453 = 268435454 + (-1). +-268435457 = -268435458 - (-1). +268435454 = 268435454 + 0. +-268435458 = -268435458 - 0. +268435455 = 268435454 + 1. +-268435459 = -268435458 - 1. +268435456 = 268435454 + 2. +-268435460 = -268435458 - 2. +268435457 = 268435454 + 3. +-268435461 = -268435458 - 3. +268435458 = 268435454 + 4. +-268435462 = -268435458 - 4. +268435459 = 268435454 + 5. +-268435463 = -268435458 - 5. +268435460 = 268435454 + 6. +-268435464 = -268435458 - 6. +268435453 = 268435455 + (-2). +-268435455 = -268435457 - (-2). +268435454 = 268435455 + (-1). +-268435456 = -268435457 - (-1). +268435455 = 268435455 + 0. +-268435457 = -268435457 - 0. +268435456 = 268435455 + 1. +-268435458 = -268435457 - 1. +268435457 = 268435455 + 2. +-268435459 = -268435457 - 2. +268435458 = 268435455 + 3. +-268435460 = -268435457 - 3. +268435459 = 268435455 + 4. +-268435461 = -268435457 - 4. +268435460 = 268435455 + 5. +-268435462 = -268435457 - 5. +268435461 = 268435455 + 6. +-268435463 = -268435457 - 6. +268435454 = 268435456 + (-2). +-268435454 = -268435456 - (-2). +268435455 = 268435456 + (-1). +-268435455 = -268435456 - (-1). +268435456 = 268435456 + 0. +-268435456 = -268435456 - 0. +268435457 = 268435456 + 1. +-268435457 = -268435456 - 1. +268435458 = 268435456 + 2. +-268435458 = -268435456 - 2. +268435459 = 268435456 + 3. +-268435459 = -268435456 - 3. +268435460 = 268435456 + 4. +-268435460 = -268435456 - 4. +268435461 = 268435456 + 5. +-268435461 = -268435456 - 5. +268435462 = 268435456 + 6. +-268435462 = -268435456 - 6. +268435455 = 268435457 + (-2). +-268435453 = -268435455 - (-2). +268435456 = 268435457 + (-1). +-268435454 = -268435455 - (-1). +268435457 = 268435457 + 0. +-268435455 = -268435455 - 0. +268435458 = 268435457 + 1. +-268435456 = -268435455 - 1. +268435459 = 268435457 + 2. +-268435457 = -268435455 - 2. +268435460 = 268435457 + 3. +-268435458 = -268435455 - 3. +268435461 = 268435457 + 4. +-268435459 = -268435455 - 4. +268435462 = 268435457 + 5. +-268435460 = -268435455 - 5. +268435463 = 268435457 + 6. +-268435461 = -268435455 - 6. +268435456 = 268435458 + (-2). +-268435452 = -268435454 - (-2). +268435457 = 268435458 + (-1). +-268435453 = -268435454 - (-1). +268435458 = 268435458 + 0. +-268435454 = -268435454 - 0. +268435459 = 268435458 + 1. +-268435455 = -268435454 - 1. +268435460 = 268435458 + 2. +-268435456 = -268435454 - 2. +268435461 = 268435458 + 3. +-268435457 = -268435454 - 3. +268435462 = 268435458 + 4. +-268435458 = -268435454 - 4. +268435463 = 268435458 + 5. +-268435459 = -268435454 - 5. +268435464 = 268435458 + 6. +-268435460 = -268435454 - 6. +268435456 = 268435454 - (-2). +-268435456 = -268435454 + (-2). +268435455 = 268435454 - (-1). +-268435455 = -268435454 + (-1). +268435454 = 268435454 - 0. +-268435454 = -268435454 + 0. +268435453 = 268435454 - 1. +-268435453 = -268435454 + 1. +268435452 = 268435454 - 2. +-268435452 = -268435454 + 2. +268435451 = 268435454 - 3. +-268435451 = -268435454 + 3. +268435450 = 268435454 - 4. +-268435450 = -268435454 + 4. +268435449 = 268435454 - 5. +-268435449 = -268435454 + 5. +268435448 = 268435454 - 6. +-268435448 = -268435454 + 6. +268435457 = 268435455 - (-2). +-268435457 = -268435455 + (-2). +268435456 = 268435455 - (-1). +-268435456 = -268435455 + (-1). +268435455 = 268435455 - 0. +-268435455 = -268435455 + 0. +268435454 = 268435455 - 1. +-268435454 = -268435455 + 1. +268435453 = 268435455 - 2. +-268435453 = -268435455 + 2. +268435452 = 268435455 - 3. +-268435452 = -268435455 + 3. +268435451 = 268435455 - 4. +-268435451 = -268435455 + 4. +268435450 = 268435455 - 5. +-268435450 = -268435455 + 5. +268435449 = 268435455 - 6. +-268435449 = -268435455 + 6. +268435458 = 268435456 - (-2). +-268435458 = -268435456 + (-2). +268435457 = 268435456 - (-1). +-268435457 = -268435456 + (-1). +268435456 = 268435456 - 0. +-268435456 = -268435456 + 0. +268435455 = 268435456 - 1. +-268435455 = -268435456 + 1. +268435454 = 268435456 - 2. +-268435454 = -268435456 + 2. +268435453 = 268435456 - 3. +-268435453 = -268435456 + 3. +268435452 = 268435456 - 4. +-268435452 = -268435456 + 4. +268435451 = 268435456 - 5. +-268435451 = -268435456 + 5. +268435450 = 268435456 - 6. +-268435450 = -268435456 + 6. +268435459 = 268435457 - (-2). +-268435459 = -268435457 + (-2). +268435458 = 268435457 - (-1). +-268435458 = -268435457 + (-1). +268435457 = 268435457 - 0. +-268435457 = -268435457 + 0. +268435456 = 268435457 - 1. +-268435456 = -268435457 + 1. +268435455 = 268435457 - 2. +-268435455 = -268435457 + 2. +268435454 = 268435457 - 3. +-268435454 = -268435457 + 3. +268435453 = 268435457 - 4. +-268435453 = -268435457 + 4. +268435452 = 268435457 - 5. +-268435452 = -268435457 + 5. +268435451 = 268435457 - 6. +-268435451 = -268435457 + 6. +268435460 = 268435458 - (-2). +-268435460 = -268435458 + (-2). +268435459 = 268435458 - (-1). +-268435459 = -268435458 + (-1). +268435458 = 268435458 - 0. +-268435458 = -268435458 + 0. +268435457 = 268435458 - 1. +-268435457 = -268435458 + 1. +268435456 = 268435458 - 2. +-268435456 = -268435458 + 2. +268435455 = 268435458 - 3. +-268435455 = -268435458 + 3. +268435454 = 268435458 - 4. +-268435454 = -268435458 + 4. +268435453 = 268435458 - 5. +-268435453 = -268435458 + 5. +268435452 = 268435458 - 6. +-268435452 = -268435458 + 6. +268435461 = 268435459 - (-2). +-268435461 = -268435459 + (-2). +268435460 = 268435459 - (-1). +-268435460 = -268435459 + (-1). +268435459 = 268435459 - 0. +-268435459 = -268435459 + 0. +268435458 = 268435459 - 1. +-268435458 = -268435459 + 1. +268435457 = 268435459 - 2. +-268435457 = -268435459 + 2. +268435456 = 268435459 - 3. +-268435456 = -268435459 + 3. +268435455 = 268435459 - 4. +-268435455 = -268435459 + 4. +268435454 = 268435459 - 5. +-268435454 = -268435459 + 5. +268435453 = 268435459 - 6. +-268435453 = -268435459 + 6. +536870907 = 536870909 + (-2). +-536870913 = -536870915 - (-2). +536870908 = 536870909 + (-1). +-536870914 = -536870915 - (-1). +536870909 = 536870909 + 0. +-536870915 = -536870915 - 0. +536870910 = 536870909 + 1. +-536870916 = -536870915 - 1. +536870911 = 536870909 + 2. +-536870917 = -536870915 - 2. +536870912 = 536870909 + 3. +-536870918 = -536870915 - 3. +536870913 = 536870909 + 4. +-536870919 = -536870915 - 4. +536870914 = 536870909 + 5. +-536870920 = -536870915 - 5. +536870915 = 536870909 + 6. +-536870921 = -536870915 - 6. +536870908 = 536870910 + (-2). +-536870912 = -536870914 - (-2). +536870909 = 536870910 + (-1). +-536870913 = -536870914 - (-1). +536870910 = 536870910 + 0. +-536870914 = -536870914 - 0. +536870911 = 536870910 + 1. +-536870915 = -536870914 - 1. +536870912 = 536870910 + 2. +-536870916 = -536870914 - 2. +536870913 = 536870910 + 3. +-536870917 = -536870914 - 3. +536870914 = 536870910 + 4. +-536870918 = -536870914 - 4. +536870915 = 536870910 + 5. +-536870919 = -536870914 - 5. +536870916 = 536870910 + 6. +-536870920 = -536870914 - 6. +536870909 = 536870911 + (-2). +-536870911 = -536870913 - (-2). +536870910 = 536870911 + (-1). +-536870912 = -536870913 - (-1). +536870911 = 536870911 + 0. +-536870913 = -536870913 - 0. +536870912 = 536870911 + 1. +-536870914 = -536870913 - 1. +536870913 = 536870911 + 2. +-536870915 = -536870913 - 2. +536870914 = 536870911 + 3. +-536870916 = -536870913 - 3. +536870915 = 536870911 + 4. +-536870917 = -536870913 - 4. +536870916 = 536870911 + 5. +-536870918 = -536870913 - 5. +536870917 = 536870911 + 6. +-536870919 = -536870913 - 6. +536870910 = 536870912 + (-2). +-536870910 = -536870912 - (-2). +536870911 = 536870912 + (-1). +-536870911 = -536870912 - (-1). +536870912 = 536870912 + 0. +-536870912 = -536870912 - 0. +536870913 = 536870912 + 1. +-536870913 = -536870912 - 1. +536870914 = 536870912 + 2. +-536870914 = -536870912 - 2. +536870915 = 536870912 + 3. +-536870915 = -536870912 - 3. +536870916 = 536870912 + 4. +-536870916 = -536870912 - 4. +536870917 = 536870912 + 5. +-536870917 = -536870912 - 5. +536870918 = 536870912 + 6. +-536870918 = -536870912 - 6. +536870911 = 536870913 + (-2). +-536870909 = -536870911 - (-2). +536870912 = 536870913 + (-1). +-536870910 = -536870911 - (-1). +536870913 = 536870913 + 0. +-536870911 = -536870911 - 0. +536870914 = 536870913 + 1. +-536870912 = -536870911 - 1. +536870915 = 536870913 + 2. +-536870913 = -536870911 - 2. +536870916 = 536870913 + 3. +-536870914 = -536870911 - 3. +536870917 = 536870913 + 4. +-536870915 = -536870911 - 4. +536870918 = 536870913 + 5. +-536870916 = -536870911 - 5. +536870919 = 536870913 + 6. +-536870917 = -536870911 - 6. +536870912 = 536870914 + (-2). +-536870908 = -536870910 - (-2). +536870913 = 536870914 + (-1). +-536870909 = -536870910 - (-1). +536870914 = 536870914 + 0. +-536870910 = -536870910 - 0. +536870915 = 536870914 + 1. +-536870911 = -536870910 - 1. +536870916 = 536870914 + 2. +-536870912 = -536870910 - 2. +536870917 = 536870914 + 3. +-536870913 = -536870910 - 3. +536870918 = 536870914 + 4. +-536870914 = -536870910 - 4. +536870919 = 536870914 + 5. +-536870915 = -536870910 - 5. +536870920 = 536870914 + 6. +-536870916 = -536870910 - 6. +536870912 = 536870910 - (-2). +-536870912 = -536870910 + (-2). +536870911 = 536870910 - (-1). +-536870911 = -536870910 + (-1). +536870910 = 536870910 - 0. +-536870910 = -536870910 + 0. +536870909 = 536870910 - 1. +-536870909 = -536870910 + 1. +536870908 = 536870910 - 2. +-536870908 = -536870910 + 2. +536870907 = 536870910 - 3. +-536870907 = -536870910 + 3. +536870906 = 536870910 - 4. +-536870906 = -536870910 + 4. +536870905 = 536870910 - 5. +-536870905 = -536870910 + 5. +536870904 = 536870910 - 6. +-536870904 = -536870910 + 6. +536870913 = 536870911 - (-2). +-536870913 = -536870911 + (-2). +536870912 = 536870911 - (-1). +-536870912 = -536870911 + (-1). +536870911 = 536870911 - 0. +-536870911 = -536870911 + 0. +536870910 = 536870911 - 1. +-536870910 = -536870911 + 1. +536870909 = 536870911 - 2. +-536870909 = -536870911 + 2. +536870908 = 536870911 - 3. +-536870908 = -536870911 + 3. +536870907 = 536870911 - 4. +-536870907 = -536870911 + 4. +536870906 = 536870911 - 5. +-536870906 = -536870911 + 5. +536870905 = 536870911 - 6. +-536870905 = -536870911 + 6. +536870914 = 536870912 - (-2). +-536870914 = -536870912 + (-2). +536870913 = 536870912 - (-1). +-536870913 = -536870912 + (-1). +536870912 = 536870912 - 0. +-536870912 = -536870912 + 0. +536870911 = 536870912 - 1. +-536870911 = -536870912 + 1. +536870910 = 536870912 - 2. +-536870910 = -536870912 + 2. +536870909 = 536870912 - 3. +-536870909 = -536870912 + 3. +536870908 = 536870912 - 4. +-536870908 = -536870912 + 4. +536870907 = 536870912 - 5. +-536870907 = -536870912 + 5. +536870906 = 536870912 - 6. +-536870906 = -536870912 + 6. +536870915 = 536870913 - (-2). +-536870915 = -536870913 + (-2). +536870914 = 536870913 - (-1). +-536870914 = -536870913 + (-1). +536870913 = 536870913 - 0. +-536870913 = -536870913 + 0. +536870912 = 536870913 - 1. +-536870912 = -536870913 + 1. +536870911 = 536870913 - 2. +-536870911 = -536870913 + 2. +536870910 = 536870913 - 3. +-536870910 = -536870913 + 3. +536870909 = 536870913 - 4. +-536870909 = -536870913 + 4. +536870908 = 536870913 - 5. +-536870908 = -536870913 + 5. +536870907 = 536870913 - 6. +-536870907 = -536870913 + 6. +536870916 = 536870914 - (-2). +-536870916 = -536870914 + (-2). +536870915 = 536870914 - (-1). +-536870915 = -536870914 + (-1). +536870914 = 536870914 - 0. +-536870914 = -536870914 + 0. +536870913 = 536870914 - 1. +-536870913 = -536870914 + 1. +536870912 = 536870914 - 2. +-536870912 = -536870914 + 2. +536870911 = 536870914 - 3. +-536870911 = -536870914 + 3. +536870910 = 536870914 - 4. +-536870910 = -536870914 + 4. +536870909 = 536870914 - 5. +-536870909 = -536870914 + 5. +536870908 = 536870914 - 6. +-536870908 = -536870914 + 6. +536870917 = 536870915 - (-2). +-536870917 = -536870915 + (-2). +536870916 = 536870915 - (-1). +-536870916 = -536870915 + (-1). +536870915 = 536870915 - 0. +-536870915 = -536870915 + 0. +536870914 = 536870915 - 1. +-536870914 = -536870915 + 1. +536870913 = 536870915 - 2. +-536870913 = -536870915 + 2. +536870912 = 536870915 - 3. +-536870912 = -536870915 + 3. +536870911 = 536870915 - 4. +-536870911 = -536870915 + 4. +536870910 = 536870915 - 5. +-536870910 = -536870915 + 5. +536870909 = 536870915 - 6. +-536870909 = -536870915 + 6. + +%% Thanks to Mikael Pettersson. Most negative fixnum (for 32/64 bits architecture). +16#8000000 = -16#8000000 div (-1). +16#8000000 = -16#8000000 * (-1). +16#8000000 = 0 - (-16#8000000). +16#800000000000000 = -16#800000000000000 div (-1). +16#800000000000000 = -16#800000000000000 * (-1). +16#800000000000000 = 0 - (-16#800000000000000). + +%% The absolute valute of the most negative fixnum used in all combinations. +1 = -16#8000000 div (-16#8000000). +1 = 16#8000000 div 16#8000000. +-1 = -16#8000000 div 16#8000000. +-1 = 16#8000000 div (-16#8000000). +1 = -16#800000000000000 div (-16#800000000000000). +1 = 16#800000000000000 div 16#800000000000000. +-1 = -16#800000000000000 div 16#800000000000000. +-1 = 16#800000000000000 div (-16#800000000000000). +0 = -16#8000000 rem (-16#8000000). +0 = 16#8000000 rem 16#8000000. +0 = -16#8000000 rem 16#8000000. +0 = 16#8000000 rem (-16#8000000). +0 = -16#800000000000000 rem (-16#800000000000000). +0 = 16#800000000000000 rem 16#800000000000000. +0 = -16#800000000000000 rem 16#800000000000000. +0 = 16#800000000000000 rem (-16#800000000000000). + +%% More border values regarding rem... +-16#8000000 = -16#8000000 rem (-16#8000001). +-16#8000000 = -16#8000000 rem 16#8000001. +1 = 16#8000001 rem (-16#8000000). +-16#800000000000000 = -16#800000000000000 rem (-16#800000000000001). +-16#800000000000000 = -16#800000000000000 rem 16#800000000000001. +1 = 16#800000000000001 rem (-16#800000000000000). +0 = 16#FFFFFFFFFFFFFFF800000000 rem 16#FFFFFFFFFFFFFFF80. + diff --git a/erts/emulator/test/big_SUITE_data/eq_28.dat b/erts/emulator/test/big_SUITE_data/eq_28.dat new file mode 100644 index 0000000000..7464632e01 --- /dev/null +++ b/erts/emulator/test/big_SUITE_data/eq_28.dat @@ -0,0 +1,3000 @@ +2639222 = -30710410 band 11032439. +-22317193 = -30710410 bor 11032439. +-24956415 = -30710410 bxor 11032439. +72453188 = -10637340 band 80972877. +-2117651 = -10637340 bor 80972877. +-74570839 = -10637340 bxor 80972877. +54550530 = 56648450 band 62977043. +65074963 = 56648450 bor 62977043. +10524433 = 56648450 bxor 62977043. +-133062592 = -46668208 band -86400951. +-6567 = -46668208 bor -86400951. +133056025 = -46668208 bxor -86400951. +11840590 = -17453746 band 29146735. +-147601 = -17453746 bor 29146735. +-11988191 = -17453746 bxor 29146735. +1052676 = -130214020 band 85129221. +-46137475 = -130214020 bor 85129221. +-47190151 = -130214020 bxor 85129221. +-117420022 = -108834726 band -16723317. +-8138021 = -108834726 bor -16723317. +109282001 = -108834726 bxor -16723317. +33558272 = 100806504 band -70250623. +-3002391 = 100806504 bor -70250623. +-36560663 = 100806504 bxor -70250623. +50333734 = -82438106 band 120065127. +-12706713 = -82438106 bor 120065127. +-63040447 = -82438106 bxor 120065127. +7078420 = -25241068 band 32318141. +-1347 = -25241068 bor 32318141. +-7079767 = -25241068 bxor 32318141. +-124059646 = -38039374 band -90241021. +-4220749 = -38039374 bor -90241021. +119838897 = -38039374 bxor -90241021. +21496192 = -8813696 band 30289337. +-20551 = -8813696 bor 30289337. +-21516743 = -8813696 bxor 30289337. +-134217378 = -53606914 band -100654753. +-20044289 = -53606914 bor -100654753. +114173089 = -53606914 bxor -100654753. +-99466204 = -88909908 band -31789963. +-21233667 = -88909908 bor -31789963. +78232537 = -88909908 bxor -31789963. +-117439478 = -50297846 band -80776069. +-13634437 = -50297846 bor -80776069. +103805041 = -50297846 bxor -80776069. +34620048 = -86752616 band 37411569. +-83961095 = -86752616 bor 37411569. +-118581143 = -86752616 bxor 37411569. +2282582 = -114633002 band 70704471. +-46211113 = -114633002 bor 70704471. +-48493695 = -114633002 bxor 70704471. +-99602428 = -82382780 band -24038099. +-6818451 = -82382780 bor -24038099. +92783977 = -82382780 bxor -24038099. +130122338 = -2782622 band 132249587. +-655373 = -2782622 bor 132249587. +-130777711 = -2782622 bxor 132249587. +-63912928 = -38482768 band -59181271. +-33751111 = -38482768 bor -59181271. +30161817 = -38482768 bxor -59181271. +8206 = -41555282 band 1712207. +-39851281 = -41555282 bor 1712207. +-39859487 = -41555282 bxor 1712207. +67109060 = -49151012 band 100719845. +-15540227 = -49151012 bor 100719845. +-82649287 = -49151012 bxor 100719845. +33686058 = -3537990 band 33714795. +-3509253 = -3537990 bor 33714795. +-37195311 = -3537990 bxor 33714795. +18939968 = 61440456 band -43556255. +-1055767 = 61440456 bor -43556255. +-19995735 = 61440456 bxor -43556255. +83918854 = -50028154 band 131320391. +-2626617 = -50028154 bor 131320391. +-86545471 = -50028154 bxor 131320391. +1098260 = 112783988 band 5686173. +117371901 = 112783988 bor 5686173. +116273641 = 112783988 bxor 5686173. +-59228158 = -50769902 band -59194397. +-50736141 = -50769902 bor -59194397. +8492017 = -50769902 bxor -59194397. +44089472 = -5455392 band 48299161. +-1245703 = -5455392 bor 48299161. +-45335175 = -5455392 bxor 48299161. +67640094 = -31958178 band 82426687. +-17171585 = -31958178 bor 82426687. +-84811679 = -31958178 bxor 82426687. +526340 = 4987916 band -29636267. +-25174691 = 4987916 bor -29636267. +-25701031 = 4987916 bxor -29636267. +50908234 = 59428714 band 55102555. +63623035 = 59428714 bor 55102555. +12714801 = 59428714 bxor 55102555. +-47930160 = -39523080 band -12802607. +-4395527 = -39523080 bor -12802607. +43534633 = -39523080 bxor -12802607. +129781814 = 134117430 band -4336841. +-1225 = 134117430 bor -4336841. +-129783039 = 134117430 bxor -4336841. +9748484 = -38281052 band 9752077. +-38277459 = -38281052 bor 9752077. +-48025943 = -38281052 bxor 9752077. +17850818 = 20046274 band 51538899. +53734355 = 20046274 bor 51538899. +35883537 = 20046274 bxor 51538899. +12853760 = 65299216 band -53658103. +-1212647 = 65299216 bor -53658103. +-14066407 = 65299216 bxor -53658103. +20494 = 4216846 band -15863249. +-11666897 = 4216846 bor -15863249. +-11687391 = 4216846 bxor -15863249. +40964 = -132865988 band 67285445. +-65621507 = -132865988 bor 67285445. +-65662471 = -132865988 bxor 67285445. +8487434 = -89266406 band 9536075. +-88217765 = -89266406 bor 9536075. +-96705199 = -89266406 bxor 9536075. +2196480 = 78218280 band 23176513. +99198313 = 78218280 bor 23176513. +97001833 = 78218280 bxor 23176513. +3364902 = -130852122 band 125040679. +-9176345 = -130852122 bor 125040679. +-12541247 = -130852122 bxor 125040679. +69341268 = 119978708 band -60664707. +-10027267 = 119978708 bor -60664707. +-79368535 = 119978708 bxor -60664707. +536386 = 21643122 band 1961923. +23068659 = 21643122 bor 1961923. +22532273 = 21643122 bxor 1961923. +25473088 = -6377408 band 29670265. +-2180231 = -6377408 bor 29670265. +-27653319 = -6377408 bxor 29670265. +-94322658 = -92741442 band -85605089. +-84023873 = -92741442 bor -85605089. +10298785 = -92741442 bxor -85605089. +5017636 = -86077332 band 5019189. +-86075779 = -86077332 bor 5019189. +-91093415 = -86077332 bxor 5019189. +-133562358 = -128038198 band -47475653. +-41951493 = -128038198 bor -47475653. +91610865 = -128038198 bxor -47475653. +18366480 = 56248152 band 87908529. +125790201 = 56248152 bor 87908529. +107423721 = 56248152 bxor 87908529. +-130807530 = -125941354 band -130729705. +-125863529 = -125941354 bor -130729705. +4944001 = -125941354 bxor -130729705. +76546052 = 81297668 band 76961517. +81713133 = 81297668 bor 76961517. +5167081 = 81297668 bxor 76961517. +13125922 = -87201502 band 30035891. +-70291533 = -87201502 bor 30035891. +-83417455 = -87201502 bxor 30035891. +-133291936 = -18962064 band -116493079. +-2163207 = -18962064 bor -116493079. +131128729 = -18962064 bxor -116493079. +43004942 = 134018414 band -91212785. +-199313 = 134018414 bor -91212785. +-43204255 = 134018414 bxor -91212785. +30434436 = 31255708 band 131102373. +131923645 = 31255708 bor 131102373. +101489209 = 31255708 bxor 131102373. +393770 = 8845946 band -31063509. +-22611333 = 8845946 bor -31063509. +-23005103 = 8845946 bxor -31063509. +51515392 = 52049544 band 66508833. +67042985 = 52049544 bor 66508833. +15527593 = 52049544 bxor 66508833. +1030 = 8012870 band -117402105. +-109390265 = 8012870 bor -117402105. +-109391295 = 8012870 bxor -117402105. +20975892 = 56636212 band -37235363. +-1575043 = 56636212 bor -37235363. +-22550935 = 56636212 bxor -37235363. +395906 = 67526354 band 428963. +67559411 = 67526354 bor 428963. +67163505 = 67526354 bxor 428963. +2181632 = 73879200 band -105813415. +-34115847 = 73879200 bor -105813415. +-36297479 = 73879200 bxor -105813415. +12850718 = -121137634 band 99368703. +-34619649 = -121137634 bor 99368703. +-47470367 = -121137634 bxor 99368703. +-117436412 = -117263156 band -83537131. +-83363875 = -117263156 bor -83537131. +34072537 = -117263156 bxor -83537131. +37929994 = 131266090 band -95433701. +-2097605 = 131266090 bor -95433701. +-40027599 = 131266090 bxor -95433701. +-66846320 = -66301512 band -25883759. +-25338951 = -66301512 bor -25883759. +41507369 = -66301512 bxor -25883759. +75500278 = 75647734 band -23785737. +-23638281 = 75647734 bor -23785737. +-99138559 = 75647734 bxor -23785737. +49476 = -99561116 band 5099469. +-94511123 = -99561116 bor 5099469. +-94560599 = -99561116 bxor 5099469. +-67100542 = -67100542 band -58612845. +-58612845 = -67100542 bor -58612845. +8487697 = -67100542 bxor -58612845. +-131032128 = -105144368 band -93021239. +-67133479 = -105144368 bor -93021239. +63898649 = -105144368 bxor -93021239. +9486542 = 26460878 band -90642961. +-73668625 = 26460878 bor -90642961. +-83155167 = 26460878 bxor -90642961. +100804740 = -16586500 band 102902661. +-14488579 = -16586500 bor 102902661. +-115293319 = -16586500 bxor 102902661. +35991562 = 61685210 band -96996853. +-71303205 = 61685210 bor -96996853. +-107294767 = 61685210 bxor -96996853. +85104640 = 85170408 band -44107007. +-44041239 = 85170408 bor -44107007. +-129145879 = 85170408 bxor -44107007. +19988902 = 95509926 band -76438553. +-917529 = 95509926 bor -76438553. +-20906431 = 95509926 bxor -76438553. +-130203116 = -84059244 band -130070979. +-83927107 = -84059244 bor -130070979. +46276009 = -84059244 bxor -130070979. +41977346 = -91902414 band 44734339. +-89145421 = -91902414 bor 44734339. +-131122767 = -91902414 bxor 44734339. +18745600 = -14770944 band 31394105. +-2122439 = -14770944 bor 31394105. +-20868039 = -14770944 bxor 31394105. +-69982114 = -69436546 band -67819297. +-67273729 = -69436546 bor -67819297. +2708385 = -69436546 bxor -67819297. +17860900 = 89164076 band 18743285. +90046461 = 89164076 bor 18743285. +72185561 = 89164076 bxor 18743285. +-134196854 = -96415350 band -131238917. +-93457413 = -96415350 bor -131238917. +40739441 = -96415350 bxor -131238917. +18023440 = 64162840 band 18589297. +64728697 = 64162840 bor 18589297. +46705257 = 64162840 bxor 18589297. +29381718 = 31620182 band -2796329. +-557865 = 31620182 bor -2796329. +-29939583 = 31620182 bxor -2796329. +7344260 = 49861060 band 91437229. +133954029 = 49861060 bor 91437229. +126609769 = 49861060 bxor 91437229. +2099042 = 2230242 band 129001331. +129132531 = 2230242 bor 129001331. +127033489 = 2230242 bxor 129001331. +34800160 = -74234320 band 104313513. +-4720967 = -74234320 bor 104313513. +-39521127 = -74234320 bxor 104313513. +16777230 = 98353198 band 52430799. +134006767 = 98353198 bor 52430799. +117229537 = 98353198 bxor 52430799. +954436 = 2004316 band -5255067. +-4205187 = 2004316 bor -5255067. +-5159623 = 2004316 bxor -5255067. +3674410 = 41464122 band 4149739. +41939451 = 41464122 bor 4149739. +38265041 = 41464122 bxor 4149739. +8390976 = -55727288 band 30543329. +-33574935 = -55727288 bor 30543329. +-41965911 = -55727288 bxor 30543329. +28320006 = 61908742 band -104914489. +-71325753 = 61908742 bor -104914489. +-99645759 = 61908742 bxor -104914489. +-109042924 = -107596812 band -75454691. +-74008579 = -107596812 bor -75454691. +35034345 = -107596812 bxor -75454691. +33554690 = 102772114 band -92138653. +-22921229 = 102772114 bor -92138653. +-56475919 = 102772114 bxor -92138653. +-58419200 = -52651168 band -41576423. +-35808391 = -52651168 bor -41576423. +22610809 = -52651168 bxor -41576423. +42500254 = 42963166 band -17268033. +-16805121 = 42963166 bor -17268033. +-59305375 = 42963166 bxor -17268033. +4197508 = 106958220 band 21929173. +124689885 = 106958220 bor 21929173. +120492377 = 106958220 bxor 21929173. +3967178 = 67099882 band 3967963. +67100667 = 67099882 bor 3967963. +63133489 = 67099882 bxor 3967963. +37761104 = 46560888 band -9883311. +-1083527 = 46560888 bor -9883311. +-38844631 = 46560888 bxor -9883311. +6686902 = 41344438 band 82709175. +117366711 = 41344438 bor 82709175. +110679809 = 41344438 bxor 82709175. +19431428 = 19431972 band 29266317. +29266861 = 19431972 bor 29266317. +9835433 = 19431972 bxor 29266317. +42605378 = -24436926 band 63871827. +-3170477 = -24436926 bor 63871827. +-45775855 = -24436926 bxor 63871827. +84777088 = 125672592 band -40912503. +-16999 = 125672592 bor -40912503. +-84794087 = 125672592 bxor -40912503. +887182 = -105910898 band 69048751. +-37749329 = -105910898 bor 69048751. +-38636511 = -105910898 bxor 69048751. +16867588 = 29880764 band 20014405. +33027581 = 29880764 bor 20014405. +16159993 = 29880764 bxor 20014405. +117440650 = 121722010 band 129245643. +133527003 = 121722010 bor 129245643. +16086353 = 121722010 bxor 129245643. +128 = -134189656 band 25694401. +-108495383 = -134189656 bor 25694401. +-108495511 = -134189656 bxor 25694401. +37748774 = 38805606 band -85913689. +-84856857 = 38805606 bor -85913689. +-122605631 = 38805606 bxor -85913689. +37925972 = 113425492 band 54786045. +130285565 = 113425492 bor 54786045. +92359593 = 113425492 bxor 54786045. +67427394 = 70114546 band 100990787. +103677939 = 70114546 bor 100990787. +36250545 = 70114546 bxor 100990787. +43581632 = 112806336 band -69396743. +-172039 = 112806336 bor -69396743. +-43753671 = 112806336 bxor -69396743. +78136350 = 129553982 band -51491681. +-74049 = 129553982 bor -51491681. +-78210399 = 129553982 bxor -51491681. +105447844 = -20364820 band 105851317. +-19961347 = -20364820 bor 105851317. +-125409191 = -20364820 bxor 105851317. +90181642 = 90708042 band 133501883. +134028283 = 90708042 bor 133501883. +43846641 = 90708042 bxor 133501883. +76840976 = -50425640 band 127249457. +-17159 = -50425640 bor 127249457. +-76858135 = -50425640 bxor 127249457. +1515542 = 68644630 band 47657111. +114786199 = 68644630 bor 47657111. +113270657 = 68644630 bxor 47657111. +36160004 = 37216900 band -18359699. +-17302803 = 37216900 bor -18359699. +-53462807 = 37216900 bxor -18359699. +-133159390 = -91003230 band -44810445. +-2654285 = -91003230 bor -44810445. +130505105 = -91003230 bxor -44810445. +-57630624 = -57498896 band -38490007. +-38358279 = -57498896 bor -38490007. +19272345 = -57498896 bxor -38490007. +-108983666 = -35304722 band -108422257. +-34743313 = -35304722 bor -108422257. +74240353 = -35304722 bxor -108422257. +1501700 = -57213412 band 56551973. +-2163139 = -57213412 bor 56551973. +-3664839 = -57213412 bxor 56551973. +926122 = -127981574 band 68051371. +-60856325 = -127981574 bor 68051371. +-61782447 = -127981574 bxor 68051371. +2162688 = 19128328 band -122092639. +-105126999 = 19128328 bor -122092639. +-107289687 = 19128328 bxor -122092639. +21449094 = 90687942 band 30371207. +99610055 = 90687942 bor 30371207. +78160961 = 90687942 bxor 30371207. +100675732 = 102429876 band 121714909. +123469053 = 102429876 bor 121714909. +22793321 = 102429876 bxor 121714909. +-33417214 = -33113006 band -5547229. +-5243021 = -33113006 bor -5547229. +28174193 = -33113006 bxor -5547229. +819200 = 30189600 band -132282919. +-102912519 = 30189600 bor -132282919. +-103731719 = 30189600 bxor -132282919. +33554974 = 36719518 band -3242369. +-77825 = 36719518 bor -3242369. +-33632799 = 36719518 bxor -3242369. +67380740 = -47962548 band 114796181. +-547107 = -47962548 bor 114796181. +-67927847 = -47962548 bxor 114796181. +12649354 = -86932566 band 13568923. +-86012997 = -86932566 bor 13568923. +-98662351 = -86932566 bxor 13568923. +43062032 = 43211576 band 64558865. +64708409 = 43211576 bor 64558865. +21646377 = 43211576 bxor 64558865. +8913014 = 10236022 band -91699593. +-90376585 = 10236022 bor -91699593. +-99289599 = 10236022 bxor -91699593. +44438084 = -4263196 band 44503885. +-4197395 = -4263196 bor 44503885. +-48635479 = -4263196 bxor 44503885. +9458178 = 59956738 band -54963437. +-4464877 = 59956738 bor -54963437. +-13923055 = 59956738 bxor -54963437. +97128768 = 99244368 band -2189495. +-73895 = 99244368 bor -2189495. +-97202663 = 99244368 bxor -2189495. +-78378930 = -11216818 band -77853329. +-10691217 = -11216818 bor -77853329. +67687713 = -11216818 bxor -77853329. +2103812 = 86227580 band -84910331. +-786563 = 86227580 bor -84910331. +-2890375 = 86227580 bxor -84910331. +131338 = -131454118 band 80089483. +-51495973 = -131454118 bor 80089483. +-51627311 = -131454118 bxor 80089483. +-32505344 = -30408088 band -6494591. +-4397335 = -30408088 bor -6494591. +28108009 = -30408088 bxor -6494591. +-58580186 = -53501146 band -41796761. +-36717721 = -53501146 bor -41796761. +21862465 = -53501146 bxor -41796761. +53496084 = 121036052 band -80713283. +-13173315 = 121036052 bor -80713283. +-66669399 = 121036052 bxor -80713283. +-117439742 = -117257294 band -34789629. +-34607181 = -117257294 bor -34789629. +82832561 = -117257294 bxor -34789629. +-114383744 = -13715840 band -109124423. +-8456519 = -13715840 bor -109124423. +105927225 = -13715840 bxor -109124423. +75575390 = 80605438 band -40816545. +-35786497 = 80605438 bor -40816545. +-111361887 = 80605438 bxor -40816545. +67113508 = -66536788 band 94376821. +-39273475 = -66536788 bor 94376821. +-106386983 = -66536788 bxor 94376821. +-134212854 = -57401590 band -129862789. +-53051525 = -57401590 bor -129862789. +81161329 = -57401590 bxor -129862789. +-100118128 = -6498920 band -93621775. +-2567 = -6498920 bor -93621775. +100115561 = -6498920 bxor -93621775. +-120061866 = -35839530 band -117781417. +-33559081 = -35839530 bor -117781417. +86502785 = -35839530 bxor -117781417. +-32231420 = -11160764 band -21742547. +-671891 = -11160764 bor -21742547. +31559529 = -11160764 bxor -21742547. +73499746 = 81888610 band 108386035. +116774899 = 81888610 bor 108386035. +43275153 = 81888610 bxor 108386035. +-133943776 = -90390608 band -112890327. +-69337159 = -90390608 bor -112890327. +64606617 = -90390608 bxor -112890327. +75793678 = 114726318 band -41095345. +-2162705 = 114726318 bor -41095345. +-77956383 = 114726318 bxor -41095345. +-133954876 = -66705700 band -123878427. +-56629251 = -66705700 bor -123878427. +77325625 = -66705700 bxor -123878427. +72486954 = 83517114 band 89338219. +100368379 = 83517114 bor 89338219. +27881425 = 83517114 bxor 89338219. +2658368 = 20763848 band -93603487. +-75498007 = 20763848 bor -93603487. +-78156375 = 20763848 bxor -93603487. +5318662 = 73378950 band -118392505. +-50332217 = 73378950 bor -118392505. +-55650879 = 73378950 bxor -118392505. +76021780 = 95319412 band -20346211. +-1048579 = 95319412 bor -20346211. +-77070359 = 95319412 bxor -20346211. +37880322 = 108661522 band 54682339. +125463539 = 108661522 bor 54682339. +87583217 = 108661522 bxor 54682339. +53555328 = -67668768 band 54080409. +-67143687 = -67668768 bor 54080409. +-120699015 = -67668768 bxor 54080409. +-131579362 = -26622370 band -131184065. +-26227073 = -26622370 bor -131184065. +105352289 = -26622370 bxor -131184065. +28676 = 34537228 band 23097429. +57605981 = 34537228 bor 23097429. +57577305 = 34537228 bxor 23097429. +117918282 = -16258454 band 130501467. +-3675269 = -16258454 bor 130501467. +-121593551 = -16258454 bxor 130501467. +-67060528 = -63766536 band -41632559. +-38338567 = -63766536 bor -41632559. +28721961 = -63766536 bxor -41632559. +86000182 = -38649034 band 119882295. +-4766921 = -38649034 bor 119882295. +-90767103 = -38649034 bxor 119882295. +8651012 = 43262884 band 13063437. +47675309 = 43262884 bor 13063437. +39024297 = 43262884 bxor 13063437. +16861378 = 98000066 band -83768621. +-2629933 = 98000066 bor -83768621. +-19491311 = 98000066 bxor -83768621. +-117369856 = -37628400 band -81709815. +-1968359 = -37628400 bor -81709815. +115401497 = -37628400 bxor -81709815. +270 = -113081586 band 1327407. +-111754449 = -113081586 bor 1327407. +-111754719 = -113081586 bxor 1327407. +-115998716 = -36289732 band -115402555. +-35693571 = -36289732 bor -115402555. +80305145 = -36289732 bxor -115402555. +-114966518 = -114834918 band -47333045. +-47201445 = -114834918 bor -47333045. +67765073 = -114834918 bxor -47333045. +-130001920 = -127772888 band -111313855. +-109084823 = -127772888 bor -111313855. +20917097 = -127772888 bxor -111313855. +50668838 = 66053606 band -82499801. +-67115033 = 66053606 bor -82499801. +-117783871 = 66053606 bxor -82499801. +-117401260 = -115753516 band -37446787. +-35799043 = -115753516 bor -37446787. +81602217 = -115753516 bxor -37446787. +33557058 = 63208050 band -31256893. +-1605901 = 63208050 bor -31256893. +-35162959 = 63208050 bxor -31256893. +287296 = 20898624 band 75788921. +96400249 = 20898624 bor 75788921. +96112953 = 20898624 bxor 75788921. +-107364322 = -103035970 band -39988193. +-35659841 = -103035970 bor -39988193. +71704481 = -103035970 bxor -39988193. +12628260 = 30339948 band 80788789. +98500477 = 30339948 bor 80788789. +85872217 = 30339948 bxor 80788789. +8683786 = 42264010 band 81105723. +114685947 = 42264010 bor 81105723. +106002161 = 42264010 bxor 81105723. +-129183216 = -59909544 band -77793359. +-8519687 = -59909544 bor -77793359. +120663529 = -59909544 bxor -77793359. +-134217706 = -34368362 band -100653033. +-803689 = -34368362 bor -100653033. +133414017 = -34368362 bxor -100653033. +34620420 = 118637572 band 43539949. +127557101 = 118637572 bor 43539949. +92936681 = 118637572 bxor 43539949. +12854306 = -104045534 band 114634419. +-2265421 = -104045534 bor 114634419. +-15119727 = -104045534 bxor 114634419. +35752032 = -26108816 band 44690409. +-17170439 = -26108816 bor 44690409. +-52922471 = -26108816 bxor 44690409. +106954766 = 124821614 band -18218225. +-351377 = 124821614 bor -18218225. +-107306143 = 124821614 bxor -18218225. +19664260 = 53219228 band 86793637. +120348605 = 53219228 bor 86793637. +100684345 = 53219228 bxor 86793637. +-83345110 = -83208838 band -3292885. +-3156613 = -83208838 bor -3292885. +80188497 = -83208838 bxor -3292885. +-123205376 = -38237816 band -123064543. +-38096983 = -38237816 bor -123064543. +85108393 = -38237816 bxor -123064543. +104875270 = -10989754 band 115688711. +-176313 = -10989754 bor 115688711. +-105051583 = -10989754 bxor 115688711. +84972564 = 84981300 band -2515875. +-2507139 = 84981300 bor -2515875. +-87479703 = 84981300 bxor -2515875. +-134084478 = -96855598 band -116970845. +-79741965 = -96855598 bor -116970845. +54342513 = -96855598 bxor -116970845. +1573120 = 69009824 band -124214951. +-56778247 = 69009824 bor -124214951. +-58351367 = 69009824 bxor -124214951. +97779998 = -33816290 band 131583487. +-12801 = -33816290 bor 131583487. +-97792799 = -33816290 bxor 131583487. +10523140 = -102721588 band 111737365. +-1507363 = -102721588 bor 111737365. +-12030503 = -102721588 bxor 111737365. +6357258 = 56824106 band 15026971. +65493819 = 56824106 bor 15026971. +59136561 = 56824106 bxor 15026971. +2367632 = 6644920 band -30661999. +-26384711 = 6644920 bor -30661999. +-28752343 = 6644920 bxor -30661999. +71158 = -126282250 band 42171895. +-84181513 = -126282250 bor 42171895. +-84252671 = -126282250 bxor 42171895. +4723780 = 107484260 band -102803763. +-43283 = 107484260 bor -102803763. +-4767063 = 107484260 bxor -102803763. +524930 = 1612674 band 40370835. +41458579 = 1612674 bor 40370835. +40933649 = 1612674 bxor 40370835. +17044160 = 130290384 band -115895607. +-2649383 = 130290384 bor -115895607. +-19693543 = 130290384 bxor -115895607. +33563854 = -29823538 band 33961199. +-29426193 = -29823538 bor 33961199. +-62990047 = -29823538 bxor 33961199. +1933956 = 10456060 band 25006725. +33528829 = 10456060 bor 25006725. +31594873 = 10456060 bxor 25006725. +-55963638 = -50718502 band -55889653. +-50644517 = -50718502 bor -55889653. +5319121 = -50718502 bxor -55889653. +82432 = 123169768 band 9032193. +132119529 = 123169768 bor 9032193. +132037097 = 123169768 bxor 9032193. +38846630 = 108062886 band -77999385. +-8783129 = 108062886 bor -77999385. +-47629759 = 108062886 bxor -77999385. +-134214636 = -114598252 band -121598659. +-101982275 = -114598252 bor -121598659. +32232361 = -114598252 bxor -121598659. +-98394110 = -13440718 band -93931901. +-8978509 = -13440718 bor -93931901. +89415601 = -13440718 bxor -93931901. +78233600 = 95014912 band 112050233. +128831545 = 95014912 bor 112050233. +50597945 = 95014912 bxor 112050233. +-58710434 = -39688578 band -53200929. +-34179073 = -39688578 bor -53200929. +24531361 = -39688578 bxor -53200929. +8463396 = 81521708 band -106879243. +-33820931 = 81521708 bor -106879243. +-42284327 = 81521708 bxor -106879243. +-110468982 = -101028726 band -110202117. +-100761861 = -101028726 bor -110202117. +9707121 = -101028726 bxor -110202117. +69213456 = 70360856 band -64340623. +-63193223 = 70360856 bor -64340623. +-132406679 = 70360856 bxor -64340623. +16925526 = 52086614 band -39369769. +-4208681 = 52086614 bor -39369769. +-21134207 = 52086614 bxor -39369769. +267396 = 103650500 band -128696403. +-25313299 = 103650500 bor -128696403. +-25580695 = 103650500 bxor -128696403. +1049186 = 68420322 band 36849267. +104220403 = 68420322 bor 36849267. +103171217 = 68420322 bxor 36849267. +8399136 = 13711664 band 60959145. +66271673 = 13711664 bor 60959145. +57872537 = 13711664 bxor 60959145. +73417230 = 108227374 band -43985201. +-9175057 = 108227374 bor -43985201. +-82592287 = 108227374 bxor -43985201. +113815620 = 113817692 band -20269211. +-20267139 = 113817692 bor -20269211. +-134082759 = 113817692 bxor -20269211. +-49414102 = -45151174 band -12709653. +-8446725 = -45151174 bor -12709653. +40967377 = -45151174 bxor -12709653. +85222464 = 123141704 band 87319777. +125239017 = 123141704 bor 87319777. +40016553 = 123141704 bxor 87319777. +16814086 = 85045766 band 57331911. +125563591 = 85045766 bor 57331911. +108749505 = 85045766 bxor 57331911. +75284 = 16889588 band -130978275. +-114163971 = 16889588 bor -130978275. +-114239255 = 16889588 bxor -130978275. +67149826 = 67561618 band 79278691. +79690483 = 67561618 bor 79278691. +12540657 = 67561618 bxor 79278691. +16338432 = 50155104 band 33279769. +67096441 = 50155104 bor 33279769. +50758009 = 50155104 bxor 33279769. +109187486 = 128383966 band -24440385. +-5243905 = 128383966 bor -24440385. +-114431391 = 128383966 bxor -24440385. +-128958332 = -111611764 band -59685931. +-42339363 = -111611764 bor -59685931. +86618969 = -111611764 bxor -59685931. +44040906 = -89982998 band 132713179. +-1310725 = -89982998 bor 132713179. +-45351631 = -89982998 bxor 132713179. +126486608 = -1406600 band 126830673. +-1062535 = -1406600 bor 126830673. +-127549143 = -1406600 bxor 126830673. +69216438 = -5199690 band 73628087. +-788041 = -5199690 bor 73628087. +-70004479 = -5199690 bxor 73628087. +61472772 = 133874980 band -72410995. +-8787 = 133874980 bor -72410995. +-61481559 = 133874980 bxor -72410995. +67279426 = -48850366 band 111934035. +-4195757 = -48850366 bor 111934035. +-71475183 = -48850366 bxor 111934035. +8454272 = -55505008 band 58830985. +-5128295 = -55505008 bor 58830985. +-13582567 = -55505008 bxor 58830985. +15730830 = 83368078 band 15853743. +83490991 = 83368078 bor 15853743. +67760161 = 83368078 bxor 15853743. +754692 = 37721276 band -104084411. +-67117827 = 37721276 bor -104084411. +-67872519 = 37721276 bxor -104084411. +106963082 = 107032474 band -16883509. +-16814117 = 107032474 bor -16883509. +-123777199 = 107032474 bxor -16883509. +46219392 = -70303576 band 115468225. +-1054743 = -70303576 bor 115468225. +-47274135 = -70303576 bxor 115468225. +34613798 = 51555174 band 101727911. +118669287 = 51555174 bor 101727911. +84055489 = 51555174 bxor 101727911. +2113108 = 69975892 band -102482179. +-34619395 = 69975892 bor -102482179. +-36732503 = 69975892 bxor -102482179. +101193282 = 101586930 band 108535363. +108929011 = 101586930 bor 108535363. +7735729 = 101586930 bxor 108535363. +19549376 = 86998208 band -105198087. +-37749255 = 86998208 bor -105198087. +-57298631 = 86998208 bxor -105198087. +48251166 = 115458366 band -84649057. +-17441857 = 115458366 bor -84649057. +-65693023 = 115458366 bxor -84649057. +-104791900 = -101735188 band -103722827. +-100666115 = -101735188 bor -103722827. +4125785 = -101735188 bxor -103722827. +25432586 = 95728458 band 30216891. +100512763 = 95728458 bor 30216891. +75080177 = 95728458 bxor 30216891. +109052688 = 128459736 band -23903439. +-4496391 = 128459736 bor -23903439. +-113549079 = 128459736 bxor -23903439. +-133162474 = -65881578 band -72343657. +-5062761 = -65881578 bor -72343657. +128099713 = -65881578 bxor -72343657. +-114843388 = -110647932 band -39329427. +-35133971 = -110647932 bor -39329427. +79709417 = -110647932 bxor -39329427. +-62390238 = -25665118 band -62054861. +-25329741 = -25665118 bor -62054861. +37060497 = -25665118 bxor -62054861. +6948192 = -92563984 band 99493737. +-18439 = -92563984 bor 99493737. +-6966631 = -92563984 bxor 99493737. +-124755826 = -90245650 band -122590577. +-88080401 = -90245650 bor -122590577. +36675425 = -90245650 bxor -122590577. +-82312956 = -73653988 band -80162523. +-71503555 = -73653988 bor -80162523. +10809401 = -73653988 bxor -80162523. +-33554262 = -24608006 band -10215253. +-1268997 = -24608006 bor -10215253. +32285265 = -24608006 bxor -10215253. +13111808 = -19385592 band 30038689. +-2458711 = -19385592 bor 30038689. +-15570519 = -19385592 bxor 30038689. +71439494 = 72078534 band 104995975. +105635015 = 72078534 bor 104995975. +34195521 = 72078534 bxor 104995975. +67139476 = 104953780 band 93388765. +131203069 = 104953780 bor 93388765. +64063593 = 104953780 bxor 93388765. +-100634110 = -23038126 band -98960861. +-21364877 = -23038126 bor -98960861. +79269233 = -23038126 bxor -98960861. +16783360 = 22567712 band -115163943. +-109379591 = 22567712 bor -115163943. +-126162951 = 22567712 bxor -115163943. +529438 = 36353694 band -66579073. +-30754817 = 36353694 bor -66579073. +-31284255 = 36353694 bxor -66579073. +3672324 = 87558476 band -126268011. +-42381859 = 87558476 bor -126268011. +-46054183 = 87558476 bxor -126268011. +8555146 = 126328490 band -124613989. +-6840645 = 126328490 bor -124613989. +-15395791 = 126328490 bxor -124613989. +-83743216 = -75338184 band -76665327. +-68260295 = -75338184 bor -76665327. +15482921 = -75338184 bxor -76665327. +12662 = 35191670 band 75838839. +111017847 = 35191670 bor 75838839. +111005185 = 35191670 bxor 75838839. +266308 = 67909092 band 66493005. +134135789 = 67909092 bor 66493005. +133869481 = 67909092 bxor 66493005. +58789890 = 126966018 band -74599917. +-6423789 = 126966018 bor -74599917. +-65213679 = 126966018 bxor -74599917. +67669056 = 88656976 band 69176905. +90164825 = 88656976 bor 69176905. +22495769 = 88656976 bxor 69176905. +67108942 = 71304014 band -57189265. +-52994193 = 71304014 bor -57189265. +-120103135 = 71304014 bxor -57189265. +121652228 = 125197692 band 130663941. +134209405 = 125197692 bor 130663941. +12557177 = 125197692 bxor 130663941. +-133890038 = -132315558 band -1617781. +-43301 = -132315558 bor -1617781. +133846737 = -132315558 bxor -1617781. +100766976 = 109696360 band -31081087. +-22151703 = 109696360 bor -31081087. +-122918679 = 109696360 bxor -31081087. +9447974 = -124441050 band 49834599. +-84054425 = -124441050 bor 49834599. +-93502399 = -124441050 bxor 49834599. +113942548 = 115007508 band -17846083. +-16781123 = 115007508 bor -17846083. +-130723671 = 115007508 bxor -17846083. +34997762 = 51775154 band 102188547. +118965939 = 51775154 bor 102188547. +83968177 = 51775154 bxor 102188547. +756096 = -124786304 band 124492729. +-1049671 = -124786304 bor 124492729. +-1805767 = -124786304 bxor 124492729. +68688734 = -61219842 band 129908575. +-1 = -61219842 bor 129908575. +-68688735 = -61219842 bxor 129908575. +16783396 = 97131948 band -81708427. +-1359875 = 97131948 bor -81708427. +-18143271 = 97131948 bxor -81708427. +-130993654 = -126633462 band -105811333. +-101451141 = -126633462 bor -105811333. +29542513 = -126633462 bxor -105811333. +68159632 = 126970008 band 72878321. +131688697 = 126970008 bor 72878321. +63529065 = 126970008 bxor 72878321. +60434518 = 127626454 band -69551273. +-2359337 = 127626454 bor -69551273. +-62793855 = 127626454 bxor -69551273. +16900 = -41912764 band 5456685. +-36472979 = -41912764 bor 5456685. +-36489879 = -41912764 bxor 5456685. +10584162 = 62488674 band -119163405. +-67258893 = 62488674 bor -119163405. +-77843055 = 62488674 bxor -119163405. +40992 = 70300336 band 55436585. +125695929 = 70300336 bor 55436585. +125654937 = 70300336 bxor 55436585. +9633806 = -88915794 band 10206799. +-88342801 = -88915794 bor 10206799. +-97976607 = -88915794 bxor 10206799. +2492612 = 107366876 band 3582693. +108456957 = 107366876 bor 3582693. +105964345 = 107366876 bxor 3582693. +24555562 = 24558010 band -67112853. +-67110405 = 24558010 bor -67112853. +-91665967 = 24558010 bxor -67112853. +2883648 = 83634120 band 2887777. +83638249 = 83634120 bor 2887777. +80754601 = 83634120 bxor 2887777. +50470918 = -70862970 band 120268871. +-1065017 = -70862970 bor 120268871. +-51535935 = -70862970 bxor 120268871. +25710612 = 26212468 band 95965597. +96467453 = 26212468 bor 95965597. +70756841 = 26212468 bxor 95965597. +79691778 = 80135698 band -51904029. +-51460109 = 80135698 bor -51904029. +-131151887 = 80135698 bxor -51904029. +130818688 = 133048288 band 130902681. +133132281 = 133048288 bor 130902681. +2313593 = 133048288 bxor 130902681. +397598 = 71774558 band 973119. +72350079 = 71774558 bor 973119. +71952481 = 71774558 bxor 973119. +66052 = 37609996 band 8460117. +46004061 = 37609996 bor 8460117. +45938009 = 37609996 bxor 8460117. +-58654646 = -53410454 band -22951333. +-17707141 = -53410454 bor -22951333. +40947505 = -53410454 bxor -22951333. +59249360 = 65868536 band -74918959. +-68299783 = 65868536 bor -74918959. +-127549143 = 65868536 bxor -74918959. +-98566090 = -26079690 band -89607881. +-17121481 = -26079690 bor -89607881. +81444609 = -26079690 bxor -89607881. +5522436 = 123496100 band 7724045. +125697709 = 123496100 bor 7724045. +120175273 = 123496100 bxor 7724045. +4719042 = -95889470 band 80554451. +-20054061 = -95889470 bor 80554451. +-24773103 = -95889470 bxor 80554451. +67584 = -95729392 band 78720009. +-17076967 = -95729392 bor 78720009. +-17144551 = -95729392 bxor 78720009. +9469966 = 47230478 band 79073327. +116833839 = 47230478 bor 79073327. +107363873 = 47230478 bxor 79073327. +16999940 = 84141628 band 20414405. +87556093 = 84141628 bor 20414405. +70556153 = 84141628 bxor 20414405. +2359306 = 82681114 band -81395637. +-1073829 = 82681114 bor -81395637. +-3433135 = 82681114 bxor -81395637. +-133889536 = -129553880 band -132820159. +-128484503 = -129553880 bor -132820159. +5405033 = -129553880 bxor -132820159. +26234918 = 95973606 band -103655897. +-33917209 = 95973606 bor -103655897. +-60152127 = 95973606 bxor -103655897. +94421076 = -34029356 band 94560893. +-33889539 = -34029356 bor 94560893. +-128310615 = -34029356 bxor 94560893. +16786754 = 17479026 band -50057789. +-49365517 = 17479026 bor -50057789. +-66152271 = 17479026 bxor -50057789. +-125829056 = -125102528 band -109041287. +-108314759 = -125102528 bor -109041287. +17514297 = -125102528 bxor -109041287. +12624414 = 80393918 band 49406751. +117176255 = 80393918 bor 49406751. +104551841 = 80393918 bxor 49406751. +16794660 = -47491476 band 55632949. +-8653187 = -47491476 bor 55632949. +-25447847 = -47491476 bxor 55632949. +80969738 = 83329226 band -52719045. +-50359557 = 83329226 bor -52719045. +-131329295 = 83329226 bxor -52719045. +69733392 = 78474584 band -13070671. +-4329479 = 78474584 bor -13070671. +-74062871 = 78474584 bxor -13070671. +73668374 = 74768278 band 99030807. +100130711 = 74768278 bor 99030807. +26462337 = 74768278 bxor 99030807. +-32504828 = -13105404 band -32086803. +-12687379 = -13105404 bor -32086803. +19817449 = -13105404 bxor -32086803. +-90960606 = -23634142 band -71561805. +-4235341 = -23634142 bor -71561805. +86725265 = -23634142 bxor -71561805. +75498080 = 112234352 band 92365545. +129101817 = 112234352 bor 92365545. +53603737 = 112234352 bxor 92365545. +72368654 = -42972306 band 81777167. +-33563793 = -42972306 bor 81777167. +-105932447 = -42972306 bxor 81777167. +58982532 = -68734308 band 58999973. +-68716867 = -68734308 bor 58999973. +-127699399 = -68734308 bxor 58999973. +13729834 = -119951238 band 13729835. +-119951237 = -119951238 bor 13729835. +-133681071 = -119951238 bxor 13729835. +33588224 = -92087160 band 35227169. +-90448215 = -92087160 bor 35227169. +-124036439 = -92087160 bxor 35227169. +-130002938 = -96314810 band -35261433. +-1573305 = -96314810 bor -35261433. +128429633 = -96314810 bxor -35261433. +103096596 = -5424844 band 107438941. +-1082499 = -5424844 bor 107438941. +-104179095 = -5424844 bxor 107438941. +2211970 = 20567250 band 14928291. +33283571 = 20567250 bor 14928291. +31071601 = 20567250 bxor 14928291. +121278464 = -8473440 band 129751129. +-775 = -8473440 bor 129751129. +-121279239 = -8473440 bxor 129751129. +1854494 = 79457310 band -94413569. +-16810753 = 79457310 bor -94413569. +-18665247 = 79457310 bxor -94413569. +532484 = 86670028 band -95903467. +-9765923 = 86670028 bor -95903467. +-10298407 = 86670028 bxor -95903467. +85329930 = -46191574 band 97962523. +-33558981 = -46191574 bor 97962523. +-118888911 = -46191574 bxor 97962523. +-108383856 = -102074440 band -107005551. +-100696135 = -102074440 bor -107005551. +7687721 = -102074440 bxor -107005551. +34201846 = 58450166 band -24253193. +-4873 = 58450166 bor -24253193. +-34206719 = 58450166 bxor -24253193. +-22522556 = -22325404 band -18031155. +-17834003 = -22325404 bor -18031155. +4688553 = -22325404 bxor -18031155. +103284866 = -190846 band 103440787. +-34925 = -190846 bor 103440787. +-103319791 = -190846 bxor 103440787. +74482112 = 75007440 band -17397303. +-16871975 = 75007440 bor -17397303. +-91354087 = 75007440 bxor -17397303. +17432782 = 124393678 band -116423697. +-9462801 = 124393678 bor -116423697. +-26895583 = 124393678 bxor -116423697. +-75487100 = -5755140 band -69928571. +-196611 = -5755140 bor -69928571. +75290489 = -5755140 bxor -69928571. +-65900534 = -7146534 band -59084789. +-330789 = -7146534 bor -59084789. +65569745 = -7146534 bxor -59084789. +4204544 = 29834984 band 108046593. +133677033 = 29834984 bor 108046593. +129472489 = 29834984 bxor 108046593. +1835430 = -113478746 band 39715303. +-75598873 = -113478746 bor 39715303. +-77434303 = -113478746 bxor 39715303. +33898516 = 105210260 band -71445443. +-133699 = 105210260 bor -71445443. +-34032215 = 105210260 bxor -71445443. +-89390078 = -89381838 band -16853629. +-16845389 = -89381838 bor -16853629. +72544689 = -89381838 bxor -16853629. +-106953984 = -35585280 band -105351367. +-33982663 = -35585280 bor -105351367. +72971321 = -35585280 bxor -105351367. +71581790 = 116674942 band -61913377. +-16820225 = 116674942 bor -61913377. +-88402015 = 116674942 bxor -61913377. +19748 = 80957228 band -132100619. +-51163139 = 80957228 bor -132100619. +-51182887 = 80957228 bxor -132100619. +100663690 = -33552502 band 118190587. +-16025605 = -33552502 bor 118190587. +-116689295 = -33552502 bxor 118190587. +11800592 = -4443624 band 16045169. +-199047 = -4443624 bor 16045169. +-11999639 = -4443624 bxor 16045169. +18158166 = 23007830 band 26555095. +31404759 = 23007830 bor 26555095. +13246593 = 23007830 bxor 26555095. +18052 = -78751804 band 78726829. +-43027 = -78751804 bor 78726829. +-61079 = -78751804 bxor 78726829. +-124770974 = -103678494 band -124770957. +-103678477 = -103678494 bor -124770957. +21092497 = -103678494 bxor -124770957. +34086944 = -88396752 band 105423017. +-17060679 = -88396752 bor 105423017. +-51147623 = -88396752 bxor 105423017. +18088974 = -107604434 band 87926223. +-37767185 = -107604434 bor 87926223. +-55856159 = -107604434 bxor 87926223. +12622404 = 14605148 band -85877147. +-83894403 = 14605148 bor -85877147. +-96516807 = 14605148 bxor -85877147. +17844010 = 124872506 band -107425813. +-397317 = 124872506 bor -107425813. +-18241327 = 124872506 bxor -107425813. +4416 = 2904392 band -112018463. +-109118487 = 2904392 bor -112018463. +-109122903 = 2904392 bxor -112018463. +36846854 = -25248506 band 36863943. +-25231417 = -25248506 bor 36863943. +-62078271 = -25248506 bxor 36863943. +89665812 = -44484108 band 90060061. +-44089859 = -44484108 bor 90060061. +-133755671 = -44484108 bxor 90060061. +-125239038 = -21388398 band -103984797. +-134157 = -21388398 bor -103984797. +125104881 = -21388398 bxor -103984797. +9043968 = 13238624 band 44959257. +49153913 = 13238624 bor 44959257. +40109945 = 13238624 bxor 44959257. +-100130658 = -95787298 band -88497985. +-84154625 = -95787298 bor -88497985. +15976033 = -95787298 bxor -88497985. +42844804 = 45994892 band -74454315. +-71304227 = 45994892 bor -74454315. +-114149031 = 45994892 bxor -74454315. +-108003126 = -74312982 band -101611045. +-67920901 = -74312982 bor -101611045. +40082225 = -74312982 bxor -101611045. +103816272 = -29713288 band 124870481. +-8659079 = -29713288 bor 124870481. +-112475351 = -29713288 bxor 124870481. +133456054 = -625738 band 133490871. +-590921 = -625738 bor 133490871. +-134046975 = -625738 bxor 133490871. +68749316 = 112789540 band -48521331. +-4481107 = 112789540 bor -48521331. +-73230423 = 112789540 bxor -48521331. +56889666 = 57546050 band 56973651. +57630035 = 57546050 bor 56973651. +740369 = 57546050 bxor 56973651. +-58686848 = -57638256 band -55597175. +-54548583 = -57638256 bor -55597175. +4138265 = -57638256 bxor -55597175. +-130022514 = -120831090 band -111003729. +-101812305 = -120831090 bor -111003729. +28210209 = -120831090 bxor -111003729. +-64867580 = -64800836 band -43895995. +-43829251 = -64800836 bor -43895995. +21038329 = -64800836 bxor -43895995. +-92009846 = -87225702 band -5988405. +-1204261 = -87225702 bor -5988405. +90805585 = -87225702 bxor -5988405. +46273152 = 63574952 band -84427071. +-67125271 = 63574952 bor -84427071. +-113398423 = 63574952 bxor -84427071. +4269094 = 31536742 band 73100711. +100368359 = 31536742 bor 73100711. +96099265 = 31536742 bxor 73100711. +-67076012 = -58670508 band -16742915. +-8337411 = -58670508 bor -16742915. +58738601 = -58670508 bxor -16742915. +-92139454 = -88452366 band -3719869. +-32781 = -88452366 bor -3719869. +92106673 = -88452366 bxor -3719869. +22054080 = 22130624 band 30704889. +30781433 = 22130624 bor 30704889. +8727353 = 22130624 bxor 30704889. +26617886 = -107566018 band 60189343. +-73994561 = -107566018 bor 60189343. +-100612447 = -107566018 bxor 60189343. +16910244 = 25298924 band -11569227. +-3180547 = 25298924 bor -11569227. +-20090791 = 25298924 bxor -11569227. +67174410 = 105729610 band 67178939. +105734139 = 105729610 bor 67178939. +38559729 = 105729610 bxor 67178939. +-112422384 = -109201704 band -78849487. +-75628807 = -109201704 bor -78849487. +36793577 = -109201704 bxor -78849487. +67109910 = -48626410 band 111480471. +-4255849 = -48626410 bor 111480471. +-71365759 = -48626410 bxor 111480471. +8611844 = -24942460 band 31713389. +-1840915 = -24942460 bor 31713389. +-10452759 = -24942460 bxor 31713389. +2186274 = 2710690 band 52559155. +53083571 = 2710690 bor 52559155. +50897297 = 2710690 bxor 52559155. +-117405600 = -116356880 band -10248599. +-9199879 = -116356880 bor -10248599. +108205721 = -116356880 bxor -10248599. +23339150 = 98869486 band 24459663. +99989999 = 98869486 bor 24459663. +76650849 = 98869486 bxor 24459663. +-133431292 = -99793892 band -66144219. +-32506819 = -99793892 bor -66144219. +100924473 = -99793892 bxor -66144219. +34987434 = -139782 band 34987947. +-139269 = -139782 bor 34987947. +-35126703 = -139782 bxor 34987947. +110133248 = 112756232 band 127381921. +130004905 = 112756232 bor 127381921. +19871657 = 112756232 bxor 127381921. +51432326 = 121364422 band -70202489. +-270393 = 121364422 bor -70202489. +-51702719 = 121364422 bxor -70202489. +5292692 = 122944180 band 6080221. +123731709 = 122944180 bor 6080221. +118439017 = 122944180 bxor 6080221. +-133951486 = -133811630 band -77293277. +-77153421 = -133811630 bor -77293277. +56798065 = -133811630 bxor -77293277. +512 = 76549664 band 40104921. +116654073 = 76549664 bor 40104921. +116653561 = 76549664 bxor 40104921. +9510942 = -72277602 band 14525567. +-67262977 = -72277602 bor 14525567. +-76773919 = -72277602 bxor 14525567. +-99163132 = -4723636 band -99158891. +-4719395 = -4723636 bor -99158891. +94443737 = -4723636 bxor -99158891. +41945482 = -91637334 band 112331163. +-21251653 = -91637334 bor 112331163. +-63197135 = -91637334 bxor 112331163. +10289424 = 27099448 band 113198353. +130008377 = 27099448 bor 113198353. +119718953 = 27099448 bxor 113198353. +42042486 = 44156534 band -23223177. +-21109129 = 44156534 bor -23223177. +-63151615 = 44156534 bxor -23223177. +-130015164 = -62555932 band -121495219. +-54035987 = -62555932 bor -121495219. +75979177 = -62555932 bxor -121495219. +1708034 = -10759166 band 4067603. +-8399597 = -10759166 bor 4067603. +-10107631 = -10759166 bxor 4067603. +51381568 = -78430384 band 127698249. +-2113703 = -78430384 bor 127698249. +-53495271 = -78430384 bxor 127698249. +86387278 = -38326706 band 91138927. +-33575057 = -38326706 bor 91138927. +-119962335 = -38326706 bxor 91138927. +-82509820 = -13303684 band -73454331. +-4248195 = -13303684 bor -73454331. +78261625 = -13303684 bxor -73454331. +4227338 = -111419046 band 6590347. +-109056037 = -111419046 bor 6590347. +-113283375 = -111419046 bxor 6590347. +118128640 = -15751064 band 124425345. +-9454359 = -15751064 bor 124425345. +-127582999 = -15751064 bxor 124425345. +100833574 = -26822362 band 126523751. +-1132185 = -26822362 bor 126523751. +-101965759 = -26822362 bxor 126523751. +-47521004 = -43326700 band -47515715. +-43321411 = -43326700 bor -47515715. +4199593 = -43326700 bxor -47515715. +51724546 = -67812942 band 52258051. +-67279437 = -67812942 bor 52258051. +-119003983 = -67812942 bxor 52258051. +-74182528 = -73589632 band -74165575. +-73572679 = -73589632 bor -74165575. +609849 = -73589632 bxor -74165575. +83550 = 57788158 band -125350305. +-67645697 = 57788158 bor -125350305. +-67729247 = 57788158 bxor -125350305. +110493732 = 133660844 band -23174795. +-7683 = 133660844 bor -23174795. +-110501415 = 133660844 bxor -23174795. +1855754 = 10441994 band -8621701. +-35461 = 10441994 bor -8621701. +-1891215 = 10441994 bxor -8621701. +39824 = 45218712 band 40945. +45219833 = 45218712 bor 40945. +45180009 = 45218712 bxor 40945. +71606870 = 107329494 band -53040553. +-17317929 = 107329494 bor -53040553. +-88924799 = 107329494 bxor -53040553. +17172484 = 93796676 band 57559597. +134183789 = 93796676 bor 57559597. +117011305 = 93796676 bxor 57559597. +-65990558 = -60982430 band -13527821. +-8519693 = -60982430 bor -13527821. +57470865 = -60982430 bxor -13527821. +-99613664 = -93280848 band -91071447. +-84738631 = -93280848 bor -91071447. +14875033 = -93280848 bxor -91071447. +-117274354 = -115610706 band -112816817. +-111153169 = -115610706 bor -112816817. +6121185 = -115610706 bxor -112816817. +-66977596 = -63804196 band -53767707. +-50594307 = -63804196 bor -53767707. +16383289 = -63804196 bxor -53767707. +67634218 = 88020154 band 101232491. +121618427 = 88020154 bor 101232491. +53984209 = 88020154 bxor 101232491. +-23043520 = -18384184 band -22517919. +-17858583 = -18384184 bor -22517919. +5184937 = -18384184 bxor -22517919. +33604102 = 54116998 band 41998151. +62511047 = 54116998 bor 41998151. +28906945 = 54116998 bxor 41998151. +71700 = -94536844 band 86186141. +-8422403 = -94536844 bor 86186141. +-8494103 = -94536844 bxor 86186141. +21594114 = 132088082 band -110518045. +-24077 = 132088082 bor -110518045. +-21618191 = 132088082 bxor -110518045. +9470080 = 59824864 band 10330521. +60685305 = 59824864 bor 10330521. +51215225 = 59824864 bxor 10330521. +-58718178 = -5202850 band -57972673. +-4457345 = -5202850 bor -57972673. +54260833 = -5202850 bxor -57972673. +9995268 = 14206220 band -73548203. +-69337251 = 14206220 bor -73548203. +-79332519 = 14206220 bxor -73548203. +79691850 = -52027286 band 131615067. +-104069 = -52027286 bor 131615067. +-79795919 = -52027286 bxor 131615067. +4202704 = 80946680 band -112661807. +-35917831 = 80946680 bor -112661807. +-40120535 = 80946680 bxor -112661807. +-100138954 = -96609994 band -95936457. +-92407497 = -96609994 bor -95936457. +7731457 = -96609994 bxor -95936457. +-67100412 = -66016860 band -6266099. +-5182547 = -66016860 bor -6266099. +61917865 = -66016860 bxor -6266099. +262338 = -24751422 band 7637203. +-17376557 = -24751422 bor 7637203. +-17638895 = -24751422 bxor 7637203. +-117432320 = -109003760 band -109239543. +-100810983 = -109003760 bor -109239543. +16621337 = -109003760 bxor -109239543. +-52373234 = -51717874 band -51060945. +-50405585 = -51717874 bor -51060945. +1967649 = -51717874 bxor -51060945. +-66486268 = -40007364 band -62134587. +-35655683 = -40007364 bor -62134587. +30830585 = -40007364 bxor -62134587. +-126207990 = -33589222 band -92651701. +-32933 = -33589222 bor -92651701. +126175057 = -33589222 bxor -92651701. +67184640 = 72875304 band -41342399. +-35651735 = 72875304 bor -41342399. +-102836375 = 72875304 bxor -41342399. +25723174 = -41092122 band 61572391. +-5242905 = -41092122 bor 61572391. +-30966079 = -41092122 bxor 61572391. +29426004 = 96715732 band 66922877. +134212605 = 96715732 bor 66922877. +104786601 = 96715732 bxor 66922877. +-134201278 = -115543950 band -54440765. +-35783437 = -115543950 bor -54440765. +98417841 = -115543950 bxor -54440765. +8601664 = 92490048 band 12050553. +95938937 = 92490048 bor 12050553. +87337273 = 92490048 bxor 12050553. +-96362466 = -79322690 band -85855713. +-68815937 = -79322690 bor -85855713. +27546529 = -79322690 bxor -85855713. +-121566940 = -51136148 band -70448331. +-17539 = -51136148 bor -70448331. +121549401 = -51136148 bxor -70448331. +87298314 = -4842550 band 87920955. +-4219909 = -4842550 bor 87920955. +-91518223 = -4842550 bxor 87920955. +1048592 = -65470376 band 13641137. +-52877831 = -65470376 bor 13641137. +-53926423 = -65470376 bxor 13641137. +-134086122 = -66966890 band -68549097. +-1429865 = -66966890 bor -68549097. +132656257 = -66966890 bxor -68549097. +83905028 = -45495804 band 118516717. +-10884115 = -45495804 bor 118516717. +-94789143 = -45495804 bxor 118516717. +3033122 = -114402782 band 8318131. +-109117773 = -114402782 bor 8318131. +-112150895 = -114402782 bxor 8318131. +26247264 = 127631984 band 26532329. +127917049 = 127631984 bor 26532329. +101669785 = 127631984 bxor 26532329. +-126771186 = -100927890 band -59662065. +-33818769 = -100927890 bor -59662065. +92952417 = -100927890 bxor -59662065. +524676 = -66169444 band 47721381. +-18972739 = -66169444 bor 47721381. +-19497415 = -66169444 bxor 47721381. +19991338 = -101381254 band 20004651. +-101367941 = -101381254 bor 20004651. +-121359279 = -101381254 bxor 20004651. +4197632 = -109498488 band 4513057. +-109183063 = -109498488 bor 4513057. +-113380695 = -109498488 bxor 4513057. +8454 = 20473158 band -33381625. +-12916921 = 20473158 bor -33381625. +-12925375 = 20473158 bxor -33381625. +19998740 = 53853236 band 24193629. +58048125 = 53853236 bor 24193629. +38049385 = 53853236 bxor 24193629. +17041538 = -117076014 band 127690915. +-6426637 = -117076014 bor 127690915. +-23468175 = -117076014 bxor 127690915. +101189376 = 109864864 band 119213913. +127889401 = 109864864 bor 119213913. +26700025 = 109864864 bxor 119213913. +-50281698 = -49752290 band -41751553. +-41222145 = -49752290 bor -41751553. +9059553 = -49752290 bxor -41751553. +14698500 = -85959220 band 98846741. +-1810979 = -85959220 bor 98846741. +-16509479 = -85959220 bxor 98846741. +19153162 = 90654506 band -115062501. +-43561157 = 90654506 bor -115062501. +-62714319 = 90654506 bxor -115062501. +9044112 = -124024136 band 13521041. +-119547207 = -124024136 bor 13521041. +-128591319 = -124024136 bxor 13521041. +8391670 = 92974070 band 45374455. +129956855 = 92974070 bor 45374455. +121565185 = 92974070 bxor 45374455. +38928452 = 47880804 band -9018163. +-65811 = 47880804 bor -9018163. +-38994263 = 47880804 bxor -9018163. +59277442 = -72511102 band 130597011. +-1191533 = -72511102 bor 130597011. +-60468975 = -72511102 bxor 130597011. +-66027328 = -2557744 band -65961783. +-2492199 = -2557744 bor -65961783. +63535129 = -2557744 bxor -65961783. +-47955250 = -47758386 band -4926737. +-4729873 = -47758386 bor -4926737. +43225377 = -47758386 bxor -4926737. +67649668 = -65220100 band 86532229. +-46337539 = -65220100 bor 86532229. +-113987207 = -65220100 bxor 86532229. +-114979318 = -76034342 band -106582261. +-67637285 = -76034342 bor -106582261. +47342033 = -76034342 bxor -106582261. +67305472 = 73601512 band -15499263. +-9203223 = 73601512 bor -15499263. +-76508695 = 73601512 bxor -15499263. +1192102 = -32244058 band 8270055. +-25166105 = -32244058 bor 8270055. +-26358207 = -32244058 bxor 8270055. +196628 = 38495380 band 20388669. +58687421 = 38495380 bor 20388669. +58490793 = 38495380 bxor 20388669. +7361538 = -51290318 band 7533699. +-51118157 = -51290318 bor 7533699. +-58479695 = -51290318 bxor 7533699. +46409216 = 130299392 band -83939783. +-49607 = 130299392 bor -83939783. +-46458823 = 130299392 bxor -83939783. +37885022 = 131218558 band -93956641. +-623105 = 131218558 bor -93956641. +-38508127 = 131218558 bxor -93956641. +68300836 = 87470636 band -56920843. +-37751043 = 87470636 bor -56920843. +-106051879 = 87470636 bxor -56920843. +8330 = 106013322 band 17068283. +123073275 = 106013322 bor 17068283. +123064945 = 106013322 bxor 17068283. +108151056 = 108184856 band -8688783. +-8654983 = 108184856 bor -8688783. +-116806039 = 108184856 bxor -8688783. +-124845738 = -55616170 band -73457193. +-4227625 = -55616170 bor -73457193. +120618113 = -55616170 bxor -73457193. +34211972 = 39525060 band -91599443. +-86286355 = 39525060 bor -91599443. +-120498327 = 39525060 bxor -91599443. +4849762 = 22804706 band -87423885. +-69468941 = 22804706 bor -87423885. +-74318703 = 22804706 bxor -87423885. +-134146272 = -112124112 band -30730327. +-8708167 = -112124112 bor -30730327. +125438105 = -112124112 bxor -30730327. +-100384754 = -12271314 band -88705841. +-592401 = -12271314 bor -88705841. +99792353 = -12271314 bxor -88705841. +39879748 = -27197860 band 66356581. +-721027 = -27197860 bor 66356581. +-40600775 = -27197860 bxor 66356581. +5210666 = 14664250 band -11563285. +-2109701 = 14664250 bor -11563285. +-7320367 = 14664250 bxor -11563285. +103612480 = 120431688 band -30600479. +-13781271 = 120431688 bor -30600479. +-117393751 = 120431688 bxor -30600479. +102107142 = -538618 band 102117063. +-528697 = -538618 bor 102117063. +-102635839 = -538618 bxor 102117063. +33864724 = -23282444 band 50789405. +-6357763 = -23282444 bor 50789405. +-40222487 = -23282444 bxor 50789405. +3690498 = 104357522 band -105058205. +-4391181 = 104357522 bor -105058205. +-8081679 = 104357522 bxor -105058205. +100676608 = 105034848 band -6537959. +-2179719 = 105034848 bor -6537959. +-102856327 = 105034848 bxor -6537959. +33554846 = -92679714 band 58994623. +-67239937 = -92679714 bor 58994623. +-100794783 = -92679714 bxor 58994623. +42635396 = 42907276 band -22375979. +-22104099 = 42907276 bor -22375979. +-64739495 = 42907276 bxor -22375979. +105121994 = 114109930 band 106301659. +115289595 = 114109930 bor 106301659. +10167601 = 114109930 bxor 106301659. +-49928624 = -38359176 band -15763887. +-4194439 = -38359176 bor -15763887. +45734185 = -38359176 bxor -15763887. +50337462 = 55066294 band -6137929. +-1409097 = 55066294 bor -6137929. +-51746559 = 55066294 bxor -6137929. +67109380 = -43824348 band 100935309. +-9998419 = -43824348 bor 100935309. +-77107799 = -43824348 bxor 100935309. +26251330 = 26316866 band -101009325. +-100943789 = 26316866 bor -101009325. +-127195119 = 26316866 bxor -101009325. +18453632 = 119272848 band -115761527. +-14942311 = 119272848 bor -115761527. +-33395943 = 119272848 bxor -115761527. +86771342 = 86797966 band -43088209. +-43061585 = 86797966 bor -43088209. +-129832927 = 86797966 bxor -43088209. +-76506620 = -9250116 band -67855803. +-599299 = -9250116 bor -67855803. +75907321 = -9250116 bxor -67855803. +8701066 = 75818394 band -106504501. +-39387173 = 75818394 bor -106504501. +-48088239 = 75818394 bxor -106504501. +-37714816 = -989528 band -37120575. +-395287 = -989528 bor -37120575. +37319529 = -989528 bxor -37120575. +75661350 = -21249690 band 96640167. +-270873 = -21249690 bor 96640167. +-75932223 = -21249690 bxor 96640167. +41993300 = -4078252 band 43568381. +-2503171 = -4078252 bor 43568381. +-44496471 = -4078252 bxor 43568381. +3279938 = 36867570 band 32660547. +66248179 = 36867570 bor 32660547. +62968241 = 36867570 bxor 32660547. +664256 = -81796416 band 69876729. +-12583943 = -81796416 bor 69876729. +-13248199 = -81796416 bxor 69876729. +114561310 = -2648258 band 114588063. +-2621505 = -2648258 bor 114588063. +-117182815 = -2648258 bxor 114588063. +75500196 = 92302060 band 113876661. +130678525 = 92302060 bor 113876661. +55178329 = 92302060 bxor 113876661. +101777418 = 120711498 band -24047429. +-5113349 = 120711498 bor -24047429. +-106890767 = 120711498 bxor -24047429. +4342032 = 41896408 band -37588687. +-34311 = 41896408 bor -37588687. +-4376343 = 41896408 bxor -37588687. +52776982 = 120410134 band 62258583. +129891735 = 120410134 bor 62258583. +77114753 = 120410134 bxor 62258583. +25897732 = 25897860 band -73666707. +-73666579 = 25897860 bor -73666707. +-99564311 = 25897860 bxor -73666707. +25318434 = -5875806 band 30596147. +-598093 = -5875806 bor 30596147. +-25916527 = -5875806 bxor 30596147. +-133099168 = -128877584 band -99281559. +-95059975 = -128877584 bor -99281559. +38039193 = -128877584 bxor -99281559. +60033166 = -4830226 band 64293007. +-570385 = -4830226 bor 64293007. +-60603551 = -4830226 bxor 64293007. +98567940 = 132802332 band 98606885. +132841277 = 132802332 bor 98606885. +34273337 = 132802332 bxor 98606885. +-64808790 = -54576902 band -64774485. +-54542597 = -54576902 bor -64774485. +10266193 = -54576902 bxor -64774485. +-134215680 = -121317112 band -98498399. +-85599831 = -121317112 bor -98498399. +48615849 = -121317112 bxor -98498399. +36924038 = -29889850 band 41646727. +-25167161 = -29889850 bor 41646727. +-62091199 = -29889850 bxor 41646727. +16780692 = -112034380 band 128224733. +-590339 = -112034380 bor 128224733. +-17371031 = -112034380 bxor 128224733. +33761282 = -96998062 band 59455523. +-71303821 = -96998062 bor 59455523. +-105065103 = -96998062 bxor 59455523. +56688640 = -76300000 band 65088217. +-67900423 = -76300000 bor 65088217. +-124589063 = -76300000 bxor 65088217. +-29163490 = -20738914 band -28363905. +-19939329 = -20738914 bor -28363905. +9224161 = -20738914 bxor -28363905. +-123696380 = -56373428 band -72311915. +-4988963 = -56373428 bor -72311915. +118707417 = -56373428 bxor -72311915. +50692234 = 64476330 band -80901989. +-67117893 = 64476330 bor -80901989. +-117810127 = 64476330 bxor -80901989. +79959056 = 82089016 band 97278993. +99408953 = 82089016 bor 97278993. +19449897 = 82089016 bxor 97278993. +1184118 = 37130614 band -120450185. +-84503689 = 37130614 bor -120450185. +-85687807 = 37130614 bxor -120450185. +567364 = -127222812 band 17410125. +-110380051 = -127222812 bor 17410125. +-110947415 = -127222812 bxor 17410125. +-87932926 = -84783358 band -87396333. +-84246765 = -84783358 bor -87396333. +3686161 = -84783358 bxor -87396333. +-134139840 = -133582256 band -95060919. +-94503335 = -133582256 bor -95060919. +39636505 = -133582256 bxor -95060919. +27285582 = -71673522 band 98695791. +-263313 = -71673522 bor 98695791. +-27548895 = -71673522 bxor 98695791. +72384516 = -60841092 band 108041221. +-25184387 = -60841092 bor 108041221. +-97568903 = -60841092 bxor 108041221. +35949578 = -68764582 band 104713867. +-293 = -68764582 bor 104713867. +-35949871 = -68764582 bxor 104713867. +54618880 = 130120552 band -76846207. +-1344535 = 130120552 bor -76846207. +-55963415 = 130120552 bxor -76846207. +-100646874 = -29080538 band -80164761. +-8598425 = -29080538 bor -80164761. +92048449 = -29080538 bxor -80164761. +14820884 = -85531116 band 98713277. +-1638723 = -85531116 bor 98713277. +-16459607 = -85531116 bxor 98713277. +10486786 = 60849330 band 83854339. +134216883 = 60849330 bor 83854339. +123730097 = 60849330 bxor 83854339. +5245312 = -128561280 band 100207033. +-33599559 = -128561280 bor 100207033. +-38844871 = -128561280 bxor 100207033. +-100396706 = -99241474 band -1286817. +-131585 = -99241474 bor -1286817. +100265121 = -99241474 bxor -1286817. +1081380 = 43049900 band 1542261. +43510781 = 43049900 bor 1542261. +42429401 = 43049900 bxor 1542261. +16936970 = 85389322 band -106729349. +-38276997 = 85389322 bor -106729349. +-55213967 = 85389322 bxor -106729349. +6555280 = 16682648 band -43698447. +-33571079 = 16682648 bor -43698447. +-40126359 = 16682648 bxor -43698447. +-97779626 = -96730410 band -68249257. +-67200041 = -96730410 bor -68249257. +30579585 = -96730410 bxor -68249257. +86020 = 127532100 band -133869267. +-6423187 = 127532100 bor -133869267. +-6509207 = 127532100 bxor -133869267. +-129404318 = -20089246 band -111578125. +-2263053 = -20089246 bor -111578125. +127141265 = -20089246 bxor -111578125. +-49246176 = -44263248 band -15543511. +-10560583 = -44263248 bor -15543511. +38685593 = -44263248 bxor -15543511. +33559566 = 34641582 band 126704719. +127786735 = 34641582 bor 126704719. +94227169 = 34641582 bxor 126704719. +-62388028 = -43348004 band -27494171. +-8454147 = -43348004 bor -27494171. +53933881 = -43348004 bxor -27494171. +4288042 = 5468090 band 57503339. +58683387 = 5468090 bor 57503339. +54395345 = 5468090 bxor 57503339. +81824832 = -16855608 band 98614881. +-65559 = -16855608 bor 98614881. +-81890391 = -16855608 bxor 98614881. +-89095162 = -88552058 band -84769209. +-84226105 = -88552058 bor -84769209. +4869057 = -88552058 bxor -84769209. +56852 = 1506932 band -49684579. +-48234499 = 1506932 bor -49684579. +-48291351 = 1506932 bxor -49684579. +-121357310 = -3916782 band -121159709. +-3719181 = -3916782 bor -121159709. +117638129 = -3916782 bxor -121159709. +-58095488 = -18903584 band -39200615. +-8711 = -18903584 bor -39200615. +58086777 = -18903584 bxor -39200615. +10618654 = 10880862 band -39585985. +-39323777 = 10880862 bor -39585985. +-49942431 = 10880862 bxor -39585985. +9838596 = -35674100 band 45507925. +-4771 = -35674100 bor 45507925. +-9843367 = -35674100 bxor 45507925. +54659146 = -12108950 band 57329755. +-9438341 = -12108950 bor 57329755. +-64097487 = -12108950 bxor 57329755. +113574096 = -18532104 band 113574353. +-18531847 = -18532104 bor 113574353. +-132105943 = -18532104 bxor 113574353. +99382 = 18195510 band 100896567. +118992695 = 18195510 bor 100896567. +118893313 = 18195510 bxor 100896567. +59396 = 11594916 band -28906995. +-17371475 = 11594916 bor -28906995. +-17430871 = 11594916 bxor -28906995. +8897986 = 42978754 band -34084909. +-4141 = 42978754 bor -34084909. +-8902127 = 42978754 bxor -34084909. +-117437952 = -77451504 band -108717559. +-68731111 = -77451504 bor -108717559. +48706841 = -77451504 bxor -108717559. +8455182 = 126944270 band -120639953. +-2150865 = 126944270 bor -120639953. +-10606047 = 126944270 bxor -120639953. +33557508 = 128134204 band -94614075. +-37379 = 128134204 bor -94614075. +-33594887 = 128134204 bxor -94614075. +545290 = 73224986 band -81101237. +-8421541 = 73224986 bor -81101237. +-8966831 = 73224986 bxor -81101237. +-124780544 = -57356248 band -105316031. +-37891735 = -57356248 bor -105316031. +86888809 = -57356248 bxor -105316031. +-132086746 = -76708122 band -123685849. +-68307225 = -76708122 bor -123685849. +63779521 = -76708122 bxor -123685849. +5390420 = 8046292 band -120360835. +-117704963 = 8046292 bor -120360835. +-123095383 = 8046292 bxor -120360835. +-111531198 = -67425422 band -44405821. +-300045 = -67425422 bor -44405821. +111231153 = -67425422 bxor -44405821. +-131918784 = -131630016 band -97806471. +-97517703 = -131630016 bor -97806471. +34401081 = -131630016 bxor -97806471. +88866846 = -45314882 band 91095327. +-43086401 = -45314882 bor 91095327. +-131953247 = -45314882 bxor 91095327. +4132 = 19405932 band -29019595. +-9617795 = 19405932 bor -29019595. +-9621927 = 19405932 bxor -29019595. +12619786 = 46184138 band -33845189. +-280837 = 46184138 bor -33845189. +-12900623 = 46184138 bxor -33845189. +2134032 = 45126488 band 2342065. +45334521 = 45126488 bor 2342065. +43200489 = 45126488 bxor 2342065. +67663126 = 77297046 band -66521833. +-56887913 = 77297046 bor -66521833. +-124551039 = 77297046 bxor -66521833. +17170436 = 21466372 band -41520403. +-37224467 = 21466372 bor -41520403. +-54394903 = 21466372 bxor -41520403. +17908002 = -107915998 band 85838771. +-39985229 = -107915998 bor 85838771. +-57893231 = -107915998 bxor 85838771. +2117728 = 20084080 band 115626217. +133592569 = 20084080 bor 115626217. +131474841 = 20084080 bxor 115626217. +85139470 = -49045138 band 94334991. +-39849617 = -49045138 bor 94334991. +-124989087 = -49045138 bxor 94334991. +52433028 = 60913820 band 52957861. +61438653 = 60913820 bor 52957861. +9005625 = 60913820 bxor 52957861. +5006890 = -27498886 band 15531563. +-16974213 = -27498886 bor 15531563. +-21981103 = -27498886 bxor 15531563. +34078720 = -90471800 band 53228577. +-71321943 = -90471800 bor 53228577. +-105400663 = -90471800 bxor 53228577. +70930438 = 70938694 band 121328135. +121336391 = 70938694 bor 121328135. +50405953 = 70938694 bxor 121328135. +10629396 = -5619916 band 16183645. +-65667 = -5619916 bor 16183645. +-10695063 = -5619916 bxor 16183645. +17891970 = 27085522 band -47118429. +-37924877 = 27085522 bor -47118429. +-55816847 = 27085522 bxor -47118429. +393728 = -112846176 band 112608857. +-631047 = -112846176 bor 112608857. +-1024775 = -112846176 bxor 112608857. +4211230 = 115425822 band 21134079. +132348671 = 115425822 bor 21134079. +128137441 = 115425822 bxor 21134079. +-117293052 = -83738420 band -109318379. +-75763747 = -83738420 bor -109318379. +41529305 = -83738420 bxor -109318379. +-87474166 = -69508566 band -87177189. +-69211589 = -69508566 bor -87177189. +18262577 = -69508566 bxor -87177189. +3671440 = -59204168 band 62482321. +-393287 = -59204168 bor 62482321. +-4064727 = -59204168 bxor 62482321. +-22789386 = -22710538 band -17380617. +-17301769 = -22710538 bor -17380617. +5487617 = -22710538 bxor -17380617. +41011524 = 49667428 band -75764787. +-67108883 = 49667428 bor -75764787. +-108120407 = 49667428 bxor -75764787. +50465922 = 53087362 band 121839507. +124460947 = 53087362 bor 121839507. +73995025 = 53087362 bxor 121839507. +6316992 = -102405168 band 6846409. +-101875751 = -102405168 bor 6846409. +-108192743 = -102405168 bxor 6846409. +91234510 = -9408818 band 100016623. +-626705 = -9408818 bor 100016623. +-91861215 = -9408818 bxor 100016623. +91571332 = 100496636 band -42481787. +-33556483 = 100496636 bor -42481787. +-125127815 = 100496636 bxor -42481787. +2664458 = 11053530 band 70053387. +78442459 = 11053530 bor 70053387. +75778001 = 11053530 bxor 70053387. +-98417664 = -13966104 band -93169919. +-8718359 = -13966104 bor -93169919. +89699305 = -13966104 bxor -93169919. +78776742 = 83331494 band 96100327. +100655079 = 83331494 bor 96100327. +21878337 = 83331494 bxor 96100327. +-114531820 = -46307436 band -114531779. +-46307395 = -46307436 bor -114531779. +68224425 = -46307436 bxor -114531779. +100798978 = 100833842 band -20769917. +-20735053 = 100833842 bor -20769917. +-121534031 = 100833842 bxor -20769917. +33644800 = 55798016 band -92150471. +-69997255 = 55798016 bor -92150471. +-103642055 = 55798016 bxor -92150471. +1582174 = 3942270 band 119104735. +121464831 = 3942270 bor 119104735. +119882657 = 3942270 bxor 119104735. +100798756 = 101061932 band 118660085. +118923261 = 101061932 bor 118660085. +18124505 = 101061932 bxor 118660085. +38350218 = 49233290 band 123301883. +134184955 = 49233290 bor 123301883. +95834737 = 49233290 bxor 123301883. +1310736 = -128624616 band 129892977. +-42375 = -128624616 bor 129892977. +-1353111 = -128624616 bxor 129892977. +16842838 = 84650070 band -70971177. +-3163945 = 84650070 bor -70971177. +-20006783 = 84650070 bxor -70971177. +-111979388 = -78389820 band -102804307. +-69214739 = -78389820 bor -102804307. +42764649 = -78389820 bxor -102804307. +-124656798 = -89000990 band -119544973. +-83889165 = -89000990 bor -119544973. +40767633 = -89000990 bxor -119544973. +-134151648 = -57470416 band -79065431. +-2384199 = -57470416 bor -79065431. +131767449 = -57470416 bxor -79065431. +88817678 = 125791278 band -37010481. +-36881 = 125791278 bor -37010481. +-88854559 = 125791278 bxor -37010481. +-100458428 = -11591332 band -100438939. +-11571843 = -11591332 bor -100438939. +88886585 = -11591332 bxor -100438939. +134442 = -107340486 band 6442475. +-101032453 = -107340486 bor 6442475. +-101166895 = -107340486 bxor 6442475. +4350272 = -61147320 band 63138273. +-2359319 = -61147320 bor 63138273. +-6709591 = -61147320 bxor 63138273. +-116076282 = -109260026 band -15344185. +-8527929 = -109260026 bor -15344185. +107548353 = -109260026 bxor -15344185. +525076 = 80494580 band 19645213. +99614717 = 80494580 bor 19645213. +99089641 = 80494580 bxor 19645213. +8390914 = -92071534 band 76058467. +-24403981 = -92071534 bor 76058467. +-32794895 = -92071534 bxor 76058467. +4613120 = 57108320 band -121211879. +-68716679 = 57108320 bor -121211879. +-73329799 = 57108320 bxor -121211879. +-132105058 = -130728738 band -118833473. +-117457153 = -130728738 bor -118833473. +14647905 = -130728738 bxor -118833473. +12654724 = -120874612 band 96549077. +-36980259 = -120874612 bor 96549077. +-49634983 = -120874612 bxor 96549077. +-65797942 = -61585174 band -48855077. +-44642309 = -61585174 bor -48855077. +21155633 = -61585174 bxor -48855077. +-28802992 = -27344264 band -26636975. +-25178247 = -27344264 bor -26636975. +3624745 = -27344264 bxor -26636975. +-115212106 = -106559050 band -76822857. +-68169801 = -106559050 bor -76822857. +47042305 = -106559050 bxor -76822857. +40406020 = -67531228 band 107523469. +-413779 = -67531228 bor 107523469. +-40819799 = -67531228 bxor 107523469. +33555266 = 125897538 band -93579437. +-1237165 = 125897538 bor -93579437. +-34792431 = 125897538 bxor -93579437. +-132972416 = -61642608 band -121662071. +-50332263 = -61642608 bor -121662071. +82640153 = -61642608 bxor -121662071. +-133131890 = -99051122 band -48835153. +-14754385 = -99051122 bor -48835153. +118377505 = -99051122 bxor -48835153. +67240196 = -64062020 band 92471621. +-38830595 = -64062020 bor 92471621. +-106070791 = -64062020 bxor 92471621. +16777354 = 59293850 band -49996341. +-7479845 = 59293850 bor -49996341. +-24257199 = 59293850 bxor -49996341. +4401280 = 4438440 band -11047743. +-11010583 = 4438440 bor -11047743. +-15411863 = 4438440 bxor -11047743. +-134199258 = -106804122 band -96089177. +-68694041 = -106804122 bor -96089177. +65505217 = -106804122 bxor -96089177. +78381140 = -34682796 band 78451709. +-34612227 = -34682796 bor 78451709. +-112993367 = -34682796 bxor 78451709. +-59750334 = -59324174 band -50758845. +-50332685 = -59324174 bor -50758845. +9417649 = -59324174 bxor -50758845. +10096832 = 43652544 band 12317433. +45873145 = 43652544 bor 12317433. +35776313 = 43652544 bxor 12317433. +10780702 = -106659266 band 78547103. +-38892865 = -106659266 bor 78547103. +-49673567 = -106659266 bxor 78547103. +2803108 = 99274220 band 4179381. +100650493 = 99274220 bor 4179381. +97847385 = 99274220 bxor 4179381. +6292490 = -127761334 band 24973243. +-109080581 = -127761334 bor 24973243. +-115373071 = -127761334 bxor 24973243. +10749968 = 44883160 band 99878961. +134012153 = 44883160 bor 99878961. +123262185 = 44883160 bxor 99878961. +37783574 = -95642858 band 48426135. +-85000297 = -95642858 bor 48426135. +-122783871 = -95642858 bxor 48426135. +38725124 = 41873028 band -87034259. +-83886355 = 41873028 bor -87034259. +-122611479 = 41873028 bxor -87034259. +-129035742 = -51424606 band -127943885. +-50332749 = -51424606 bor -127943885. +78702993 = -51424606 bxor -127943885. +134240 = -130126096 band 100830313. +-29430023 = -130126096 bor 100830313. +-29564263 = -130126096 bxor 100830313. +-133114226 = -132909330 band -3090545. +-2885649 = -132909330 bor -3090545. +130228577 = -132909330 bxor -3090545. +2261508 = 87263772 band -122780123. +-37777859 = 87263772 bor -122780123. +-40039367 = 87263772 bxor -122780123. +76288426 = 80516090 band -41067093. +-36839429 = 80516090 bor -41067093. +-113127855 = 80516090 bxor -41067093. +6556672 = 83700744 band -110731359. +-33587287 = 83700744 bor -110731359. +-40143959 = 83700744 bxor -110731359. +-134078074 = -113248826 band -96327289. +-75498041 = -113248826 bor -96327289. +58580033 = -113248826 bxor -96327289. +-131596140 = -63110988 band -77048611. +-8563459 = -63110988 bor -77048611. +123032681 = -63110988 bxor -77048611. +360450 = 87402578 band 42850083. +129892211 = 87402578 bor 42850083. +129531761 = 87402578 bxor 42850083. +67264512 = 100889632 band -40214055. +-6588935 = 100889632 bor -40214055. +-73853447 = 100889632 bxor -40214055. +4243998 = -77465698 band 73187967. +-8521729 = -77465698 bor 73187967. +-12765727 = -77465698 bxor 73187967. +-113114620 = -67390900 band -45727083. +-3363 = -67390900 bor -45727083. +113111257 = -67390900 bxor -45727083. +33621898 = 57798570 band 100992923. +125169595 = 57798570 bor 100992923. +91547697 = 57798570 bxor 100992923. +1385232 = 89630520 band -124423407. +-36178119 = 89630520 bor -124423407. +-37563351 = 89630520 bxor -124423407. +131190 = 14113910 band 52593271. +66575991 = 14113910 bor 52593271. +66444801 = 14113910 bxor 52593271. +-129421756 = -126091548 band -53661875. +-50331667 = -126091548 bor -53661875. +79090089 = -126091548 bxor -53661875. +-99563006 = -95106558 band -80556269. +-76099821 = -95106558 bor -80556269. +23463185 = -95106558 bxor -80556269. +-129490624 = -76798640 band -62229687. +-9537703 = -76798640 bor -62229687. +119952921 = -76798640 bxor -62229687. +-62848946 = -28736434 band -34518673. +-406161 = -28736434 bor -34518673. +62442785 = -28736434 bxor -34518673. +-130792956 = -17414532 band -130155771. +-16777347 = -17414532 bor -130155771. +114015609 = -17414532 bxor -130155771. +19989770 = -4352166 band 24317323. +-24613 = -4352166 bor 24317323. +-20014383 = -4352166 bxor 24317323. +541184 = 10440296 band -98024831. +-88125719 = 10440296 bor -98024831. +-88666903 = 10440296 bxor -98024831. +-134166746 = -131215578 band -33360025. +-30408857 = -131215578 bor -33360025. +103757889 = -131215578 bxor -33360025. +-117145324 = -11605740 band -116030019. +-10490435 = -11605740 bor -116030019. +106654889 = -11605740 bxor -116030019. +-99245310 = -99108942 band -71458045. +-71321677 = -99108942 bor -71458045. +27923633 = -99108942 bxor -71458045. +110723200 = -21265792 band 110739641. +-21249351 = -21265792 bor 110739641. +-131972551 = -21265792 bxor 110739641. +4525150 = 4562174 band -34771873. +-34734849 = 4562174 bor -34771873. +-39259999 = 4562174 bxor -34771873. +92538404 = 93734572 band -7557259. +-6361091 = 93734572 bor -7557259. +-98899495 = 93734572 bxor -7557259. +133898 = 98208522 band -131698821. +-33624197 = 98208522 bor -131698821. +-33758095 = 98208522 bxor -131698821. +328080 = 41361816 band -58339855. +-17306119 = 41361816 bor -58339855. +-17634199 = 41361816 bxor -58339855. +16910422 = 52317654 band -115177385. +-79770153 = 52317654 bor -115177385. +-96680575 = 52317654 bxor -115177385. +34084868 = 59293508 band -31958995. +-6750355 = 59293508 bor -31958995. +-40835223 = 59293508 bxor -31958995. +50942050 = -83267230 band 123556595. +-10652685 = -83267230 bor 123556595. +-61594735 = -83267230 bxor 123556595. +12847648 = -51082320 band 13584937. +-50345031 = -51082320 bor 13584937. +-63192679 = -51082320 bxor 13584937. +17826062 = 93405614 band -76534961. +-955409 = 93405614 bor -76534961. +-18781471 = 93405614 bxor -76534961. +529092 = -99700004 band 82403301. +-17825795 = -99700004 bor 82403301. +-18354887 = -99700004 bxor 82403301. +2230314 = 45337274 band 70135147. +113242107 = 45337274 bor 70135147. +111011793 = 45337274 bxor 70135147. +88080448 = 88219848 band 97850721. +97990121 = 88219848 bor 97850721. +9909673 = 88219848 bxor 97850721. +4102 = 38000774 band 8402247. +46398919 = 38000774 bor 8402247. +46394817 = 38000774 bxor 8402247. +2916372 = 45908340 band -43211107. +-219139 = 45908340 bor -43211107. +-3135511 = 45908340 bxor -43211107. +-134162942 = -59443438 band -83829021. +-9109517 = -59443438 bor -83829021. +125053425 = -59443438 bxor -83829021. +-120455040 = -103137056 band -17690727. +-372743 = -103137056 bor -17690727. +120082297 = -103137056 bxor -17690727. +50332190 = 120025694 band 56133183. +125826687 = 120025694 bor 56133183. +75494497 = 120025694 bxor 56133183. +21104644 = -112030964 band 97193045. +-35942563 = -112030964 bor 97193045. +-57047207 = -112030964 bxor 97193045. +22038090 = 66344554 band 22628187. +66934651 = 66344554 bor 22628187. +44896561 = 66344554 bxor 22628187. +35719376 = 35867640 band 66918609. +67066873 = 35867640 bor 66918609. +31347497 = 35867640 bxor 66918609. +14183990 = 49901366 band -35979721. +-262345 = 49901366 bor -35979721. +-14446335 = 49901366 bxor -35979721. +69804292 = 87895972 band -60198643. +-42106963 = 87895972 bor -60198643. +-111911255 = 87895972 bxor -60198643. +71647426 = 107301058 band -44611885. +-8958253 = 107301058 bor -44611885. +-80605679 = 107301058 bxor -44611885. +80281600 = -1072624 band 80285961. +-1068263 = -1072624 bor 80285961. +-81349863 = -1072624 bxor 80285961. +4271374 = 46345998 band -129663697. +-87589073 = 46345998 bor -129663697. +-91860447 = 46345998 bxor -129663697. +50365444 = 51695420 band -77024059. +-75694083 = 51695420 bor -77024059. +-126059527 = 51695420 bxor -77024059. +-133813238 = -133747174 band -46744245. +-46678181 = -133747174 bor -46744245. +87135057 = -133747174 bxor -46744245. +10780672 = 16622376 band -56305599. +-50463895 = 16622376 bor -56305599. +-61244567 = 16622376 bxor -56305599. +-133168858 = -10874394 band -122559705. +-265241 = -10874394 bor -122559705. +132903617 = -10874394 bxor -122559705. +67469652 = -31602220 band 69580669. +-29491203 = -31602220 bor 69580669. +-96960855 = -31602220 bxor 69580669. +-125500862 = -106600846 band -19952957. +-1052941 = -106600846 bor -19952957. +124447921 = -106600846 bxor -19952957. +5443136 = 7843648 band 98258553. +100659065 = 7843648 bor 98258553. +95215929 = 7843648 bxor 98258553. +43388958 = -86018114 band 43388959. +-86018113 = -86018114 bor 43388959. +-129407071 = -86018114 bxor 43388959. +-125282012 = -104300692 band -88516299. +-67534979 = -104300692 bor -88516299. +57747033 = -104300692 bxor -88516299. +102039818 = -32026166 band 118853435. +-15212549 = -32026166 bor 118853435. +-117252367 = -32026166 bxor 118853435. +-131071472 = -126605736 band -46967887. +-42502151 = -126605736 bor -46967887. +88569321 = -126605736 bxor -46967887. +104906774 = -29310826 band 105112599. +-29105001 = -29310826 bor 105112599. +-134011775 = -29310826 bxor 105112599. +19943428 = -80654332 band 24672749. +-75925011 = -80654332 bor 24672749. +-95868439 = -80654332 bxor 24672749. +-109051870 = -4173790 band -107435341. +-2557261 = -4173790 bor -107435341. +106494609 = -4173790 bxor -107435341. +23412832 = 58026096 band 91211753. +125825017 = 58026096 bor 91211753. +102412185 = 58026096 bxor 91211753. +2165774 = 112675950 band 6897423. +117407599 = 112675950 bor 6897423. +115241825 = 112675950 bxor 6897423. +2136452 = 44080028 band 74709413. +116652989 = 44080028 bor 74709413. +114516537 = 44080028 bxor 74709413. +295210 = 101695866 band 310571. +101711227 = 101695866 bor 310571. +101416017 = 101695866 bxor 310571. +-121011968 = -35007096 band -87061727. +-1056855 = -35007096 bor -87061727. +119955113 = -35007096 bxor -87061727. +16777478 = 55081798 band -108003065. +-69698745 = 55081798 bor -108003065. +-86476223 = 55081798 bxor -108003065. +67665940 = 84591156 band 83408989. +100334205 = 84591156 bor 83408989. +32668265 = 84591156 bxor 83408989. +16843906 = -83819054 band 27371171. +-73291789 = -83819054 bor 27371171. +-90135695 = -83819054 bxor 27371171. +109661440 = 128699808 band 109935961. +128974329 = 128699808 bor 109935961. +19312889 = 128699808 bxor 109935961. +264478 = 38120734 band 94243327. +132099583 = 38120734 bor 94243327. +131835105 = 38120734 bxor 94243327. +83886596 = 93332428 band 84907541. +94353373 = 93332428 bor 84907541. +10466777 = 93332428 bxor 84907541. +9651466 = 10190122 band -86816997. +-86278341 = 10190122 bor -86816997. +-95929807 = 10190122 bxor -86816997. +12432 = 92385464 band 39878289. +132251321 = 92385464 bor 39878289. +132238889 = 92385464 bxor 39878289. +38011382 = -20168202 band 55917047. +-2262537 = -20168202 bor 55917047. +-40273919 = -20168202 bxor 55917047. +50143300 = -16965532 band 50164429. +-16944403 = -16965532 bor 50164429. +-67087703 = -16965532 bxor 50164429. +68159106 = 108169090 band 77168275. +117178259 = 108169090 bor 77168275. +49019153 = 108169090 bxor 77168275. +43601600 = 43900624 band -67408183. +-67109159 = 43900624 bor -67408183. +-110710759 = 43900624 bxor -67408183. +-96399154 = -28993074 band -70029073. +-2622993 = -28993074 bor -70029073. +93776161 = -28993074 bxor -70029073. +71435908 = -45475844 band 79900293. +-37011459 = -45475844 bor 79900293. +-108447367 = -45475844 bxor 79900293. +-67107830 = -14318374 band -66048757. +-13259301 = -14318374 bor -66048757. +53848529 = -14318374 bxor -66048757. +796160 = 35567592 band -124965375. +-90193943 = 35567592 bor -124965375. +-90990103 = 35567592 bxor -124965375. +132262 = -35187546 band 34770663. +-549145 = -35187546 bor 34770663. +-681407 = -35187546 bxor 34770663. +51980308 = 119237268 band 60664125. +127921085 = 119237268 bor 60664125. +75940777 = 119237268 bxor 60664125. +30347266 = 98555186 band -101764477. +-33556557 = 98555186 bor -101764477. +-63903823 = 98555186 bxor -101764477. +39936 = 9346048 band -129983431. +-120677319 = 9346048 bor -129983431. +-120717255 = 9346048 bxor -129983431. +2101854 = 3281534 band 40399839. +41579519 = 3281534 bor 40399839. +39477665 = 3281534 bxor 40399839. +117522468 = 121731116 band 126206709. +130415357 = 121731116 bor 126206709. +12892889 = 121731116 bxor 126206709. +34097290 = 64542858 band -99979525. +-69533957 = 64542858 bor -99979525. +-103631247 = 64542858 bxor -99979525. +18909456 = 90434328 band -105080463. +-33555591 = 90434328 bor -105080463. +-52465047 = 90434328 bxor -105080463. +33747798 = -93064362 band 34013143. +-92799017 = -93064362 bor 34013143. +-126546815 = -93064362 bxor 34013143. +36700292 = 104374468 band 45112237. +112786413 = 104374468 bor 45112237. +76086121 = 104374468 bxor 45112237. +13746786 = 97775330 band 47301235. +131329779 = 97775330 bor 47301235. +117582993 = 97775330 bxor 47301235. +75498784 = 75564336 band -39582295. +-39516743 = 75564336 bor -39582295. +-115015527 = 75564336 bxor -39582295. +38015502 = 38147886 band -25423153. +-25290769 = 38147886 bor -25423153. +-63306271 = 38147886 bxor -25423153. +17317956 = 61424732 band -49392795. +-5286019 = 61424732 bor -49392795. +-22603975 = 61424732 bxor -49392795. +8390698 = 27293754 band -53408533. +-34505477 = 27293754 bor -53408533. +-42896175 = 27293754 bxor -53408533. +-99336128 = -4961720 band -99237663. +-4863255 = -4961720 bor -99237663. +94472873 = -4961720 bxor -99237663. +-117339130 = -82977274 band -47084345. +-12722489 = -82977274 bor -47084345. +104616641 = -82977274 bxor -47084345. +-3898860 = -1588492 band -3372515. +-1062147 = -1588492 bor -3372515. +2836713 = -1588492 bxor -3372515. +-99613694 = -73804654 band -97505693. +-71696653 = -73804654 bor -97505693. +27917041 = -73804654 bxor -97505693. +-131593728 = -130540960 band -30627047. +-29574279 = -130540960 bor -30627047. +102019449 = -130540960 bxor -30627047. +40633758 = 58501086 band -85111361. +-67244033 = 58501086 bor -85111361. +-107877791 = 58501086 bxor -85111361. +5266564 = 91520140 band 13885397. +100138973 = 91520140 bor 13885397. +94872409 = 91520140 bxor 13885397. +-64814390 = -64527382 band -30210341. +-29923333 = -64527382 bor -30210341. +34891057 = -64527382 bxor -30210341. +3310672 = 3331448 band 92251217. +92271993 = 3331448 bor 92251217. +88961321 = 3331448 bxor 92251217. +50402486 = 51369142 band -78563913. +-77597257 = 51369142 bor -78563913. +-127999743 = 51369142 bxor -78563913. +38342660 = 41668900 band -28756851. +-25430611 = 41668900 bor -28756851. +-63773271 = 41668900 bxor -28756851. +70780482 = 87852610 band 79263315. +96335443 = 87852610 bor 79263315. +25554961 = 87852610 bxor 79263315. +-132085632 = -63513712 band -73298807. +-4726887 = -63513712 bor -73298807. +127358745 = -63513712 bxor -73298807. +1049742 = 126928014 band -128244561. +-2366289 = 126928014 bor -128244561. +-3416031 = 126928014 bxor -128244561. +33824772 = 39198908 band -99784635. +-94410499 = 39198908 bor -99784635. +-128235271 = 39198908 bxor -99784635. +26744970 = 131636122 band -104899381. +-8229 = 131636122 bor -104899381. +-26753199 = 131636122 bxor -104899381. +75497600 = 79858856 band -6208575. +-1847319 = 79858856 bor -6208575. +-77344919 = 79858856 bxor -6208575. +8704550 = 43308902 band 31783591. +66387943 = 43308902 bor 31783591. +57683393 = 43308902 bxor 31783591. +84232788 = 117951316 band 87907069. +121625597 = 117951316 bor 87907069. +37392809 = 117951316 bxor 87907069. +8651330 = -108592142 band 14457411. +-102786061 = -108592142 bor 14457411. +-111437391 = -108592142 bxor 14457411. +125831360 = 130042048 band 126462457. +130673145 = 130042048 bor 126462457. +4841785 = 130042048 bxor 126462457. +69469470 = 117271870 band -47933537. +-131137 = 117271870 bor -47933537. +-69600607 = 117271870 bxor -47933537. +42016932 = 46215404 band -72225611. +-68027139 = 46215404 bor -72225611. +-110044071 = 46215404 bxor -72225611. +-121303542 = -102817974 band -54194501. +-35708933 = -102817974 bor -54194501. +85594609 = -102817974 bxor -54194501. +33558288 = -100241448 band 65118001. +-68681735 = -100241448 bor 65118001. +-102240023 = -100241448 bxor 65118001. +69452310 = 108520982 band 69983127. +109051799 = 108520982 bor 69983127. +39599489 = 108520982 bxor 69983127. +22982916 = 22983044 band -8389267. +-8389139 = 22983044 bor -8389267. +-31372055 = 22983044 bxor -8389267. +2082 = -133935710 band 113809971. +-20127821 = -133935710 bor 113809971. +-20129903 = -133935710 bxor 113809971. +262496 = -120102416 band 53216105. +-67148807 = -120102416 bor 53216105. +-67411303 = -120102416 bxor 53216105. +73965710 = -16932370 band 90744463. +-153617 = -16932370 bor 90744463. +-74119327 = -16932370 bxor 90744463. +6827268 = 32025884 band 75001125. +100199741 = 32025884 bor 75001125. +93372473 = 32025884 bxor 75001125. +68778 = -131731718 band 106110123. +-25690373 = -131731718 bor 106110123. +-25759151 = -131731718 bxor 106110123. +23148032 = -77496568 band 90683041. +-9961559 = -77496568 bor 90683041. +-33109591 = -77496568 bxor 90683041. +262278 = -128712506 band 52746375. +-76228409 = -128712506 bor 52746375. +-76490687 = -128712506 bxor 52746375. +916 = 1278900 band -72868899. +-71590915 = 1278900 bor -72868899. +-71591831 = 1278900 bxor -72868899. +-127114750 = -117480622 band -127109597. +-117475469 = -117480622 bor -127109597. +9639281 = -117480622 bxor -127109597. +68091904 = 71247648 band -7366439. +-4210695 = 71247648 bor -7366439. +-72302599 = 71247648 bxor -7366439. +17055774 = 25977502 band 50745727. +59667455 = 25977502 bor 50745727. +42611681 = 25977502 bxor 50745727. +-57179900 = -37776052 band -19404395. +-547 = -37776052 bor -19404395. +57179353 = -37776052 bxor -19404395. +18350730 = -111670614 band 121144987. +-8876357 = -111670614 bor 121144987. +-27227087 = -111670614 bxor 121144987. +34769424 = 49723960 band -15037935. +-83399 = 49723960 bor -15037935. +-34852823 = 49723960 bxor -15037935. +-58449546 = -24893578 band -40963721. +-7407753 = -24893578 bor -40963721. +51041793 = -24893578 bxor -40963721. +-66584508 = -59162140 band -66275763. +-58853395 = -59162140 bor -66275763. +7731113 = -59162140 bxor -66275763. +16974850 = -41728766 band 24587795. +-34115821 = -41728766 bor 24587795. +-51090671 = -41728766 bxor 24587795. +91883584 = 91920464 band -42243511. +-42206631 = 91920464 bor -42243511. +-134090215 = 91920464 bxor -42243511. +84183118 = 90484558 band -40069009. +-33767569 = 90484558 bor -40069009. +-117950687 = 90484558 bxor -40069009. +24580 = 116975996 band 17261061. +134212477 = 116975996 bor 17261061. +134187897 = 116975996 bxor 17261061. +16394 = 81818202 band 33836171. +115637979 = 81818202 bor 33836171. +115621585 = 81818202 bxor 33836171. +27328768 = -106356376 band 60889473. +-72795671 = -106356376 bor 60889473. +-100124439 = -106356376 bxor 60889473. +-64945626 = -64792026 band -1497497. +-1343897 = -64792026 bor -1497497. +63601729 = -64792026 bxor -1497497. +41995284 = -89986028 band 113560765. +-18420547 = -89986028 bor 113560765. +-60415831 = -89986028 bxor 113560765. +122864130 = -10816846 band 123191811. +-10489165 = -10816846 bor 123191811. +-133353295 = -10816846 bxor 123191811. +-62638720 = -20138624 band -42567751. +-67655 = -20138624 bor -42567751. +62571065 = -20138624 bxor -42567751. +33555294 = 100763646 band 42629983. +109838335 = 100763646 bor 42629983. +76283041 = 100763646 bxor 42629983. +360484 = 17279404 band -50473355. +-33554435 = 17279404 bor -50473355. +-33914919 = 17279404 bxor -50473355. +33564170 = 48899594 band -83530117. +-68194693 = 48899594 bor -83530117. +-101758863 = 48899594 bxor -83530117. +84026512 = 119256216 band -43883279. +-8653575 = 119256216 bor -43883279. +-92680087 = 119256216 bxor -43883279. +4182 = 17602774 band 74610519. +92209111 = 17602774 bor 74610519. +92204929 = 17602774 bxor 74610519. +19071492 = -110919100 band 94854957. +-35135635 = -110919100 bor 94854957. +-54207127 = -110919100 bxor 94854957. +17899618 = 17919074 band -113430029. +-113410573 = 17919074 bor -113430029. +-131310191 = 17919074 bxor -113430029. +-117424096 = -113738064 band -3686103. +-71 = -113738064 bor -3686103. +117424025 = -113738064 bxor -3686103. +9234446 = 60681390 band 82770511. +134217455 = 60681390 bor 82770511. +124983009 = 60681390 bxor 82770511. +1197252 = 35575260 band 7489253. +41867261 = 35575260 bor 7489253. +40670009 = 35575260 bxor 7489253. +-130014166 = -60807750 band -129307541. +-60101125 = -60807750 bor -129307541. +69913041 = -60807750 bxor -129307541. +8478784 = 28406728 band -24810399. +-4882455 = 28406728 bor -24810399. +-13361239 = 28406728 bxor -24810399. +17358854 = -103095418 band 53077063. +-67377209 = -103095418 bor 53077063. +-84736063 = -103095418 bxor 53077063. +38405140 = 38667380 band 105606557. +105868797 = 38667380 bor 105606557. +67463657 = 38667380 bxor 105606557. +1060866 = -34491886 band 1474019. +-34078733 = -34491886 bor 1474019. +-35139599 = -34491886 bxor 1474019. +67125888 = 75559904 band 74860185. +83294201 = 75559904 bor 74860185. +16168313 = 75559904 bxor 74860185. +18879774 = 53796190 band -39250625. +-4334209 = 53796190 bor -39250625. +-23213983 = 53796190 bxor -39250625. +1122820 = 53571084 band 81507157. +133955421 = 53571084 bor 81507157. +132832601 = 53571084 bxor 81507157. +10567754 = -85102230 band 27510363. +-68159621 = -85102230 bor 27510363. +-78727375 = -85102230 bxor 27510363. +8457936 = -24289544 band 15806417. +-16941063 = -24289544 bor 15806417. +-25398999 = -24289544 bxor 15806417. +29894710 = -1492426 band 30305591. +-1081545 = -1492426 bor 30305591. +-30976255 = -1492426 bxor 30305591. +-133861372 = -105549148 band -100141043. +-71828819 = -105549148 bor -100141043. +62032553 = -105549148 bxor -100141043. +-100499006 = -100219966 band -23943725. +-23664685 = -100219966 bor -23943725. +76834321 = -100219966 bxor -23943725. +50921472 = 120132880 band -79099895. +-9888487 = 120132880 bor -79099895. +-60809959 = 120132880 bxor -79099895. +-100579314 = -25077234 band -78132177. +-2630097 = -25077234 bor -78132177. +97949217 = -25077234 bxor -78132177. +-9432572 = -888260 band -9364539. +-820227 = -888260 bor -9364539. +8612345 = -888260 bxor -9364539. +10225674 = -117634790 band 10419275. +-117441189 = -117634790 bor 10419275. +-127666863 = -117634790 bxor 10419275. +9728 = 26375720 band 105688897. +132054889 = 26375720 bor 105688897. +132045161 = 26375720 bxor 105688897. +22155302 = -112026394 band 64950823. +-69230873 = -112026394 bor 64950823. +-91386175 = -112026394 bxor 64950823. +77646932 = -22229804 band 99876477. +-259 = -22229804 bor 99876477. +-77647191 = -22229804 bxor 99876477. +41282 = 35365234 band 18917827. +54241779 = 35365234 bor 18917827. +54200497 = 35365234 bxor 18917827. +37945408 = -25959872 band 63374713. +-530567 = -25959872 bor 63374713. +-38475975 = -25959872 bxor 63374713. +39453214 = 67003070 band 39460639. +67010495 = 67003070 bor 39460639. +27557281 = 67003070 bxor 39460639. +32804 = 114614892 band 19497013. +134079101 = 114614892 bor 19497013. +134046297 = 114614892 bxor 19497013. +9014282 = 28961994 band 9145915. +29093627 = 28961994 bor 9145915. +20079345 = 28961994 bxor 9145915. +90351632 = -43796136 band 134146737. +-1031 = -43796136 bor 134146737. +-90352663 = -43796136 bxor 134146737. +-124648682 = -118355050 band -90516713. +-84223081 = -118355050 bor -90516713. +40425601 = -118355050 bxor -90516713. +33947652 = -83422460 band 48660717. +-68709395 = -83422460 bor 48660717. +-102657047 = -83422460 bxor 48660717. +-106231518 = -71611614 band -34633293. +-13389 = -71611614 bor -34633293. +106218129 = -71611614 bxor -34633293. +-64742816 = -26977424 band -46711063. +-8945671 = -26977424 bor -46711063. +55797145 = -26977424 bxor -46711063. +80086542 = 115799918 band -53539313. +-17825937 = 115799918 bor -53539313. +-97912479 = 115799918 bxor -53539313. +761988 = -116670820 band 112976037. +-4456771 = -116670820 bor 112976037. +-5218759 = -116670820 bxor 112976037. +531498 = 17767546 band -25658325. +-8422277 = 17767546 bor -25658325. +-8953775 = 17767546 bxor -25658325. +52699136 = 56895624 band 120513057. +124709545 = 56895624 bor 120513057. +72010409 = 56895624 bxor 120513057. +67141638 = -27097530 band 83931143. +-10308025 = -27097530 bor 83931143. +-77449663 = -27097530 bxor 83931143. +22430996 = 56050996 band -42565795. +-8945795 = 56050996 bor -42565795. +-31376791 = 56050996 bxor -42565795. +69222530 = 87081170 band 82724259. +100582899 = 87081170 bor 82724259. +31360369 = 87081170 bxor 82724259. +10518528 = 29196448 band 111195225. +129873145 = 29196448 bor 111195225. +119354617 = 29196448 bxor 111195225. +-99346402 = -13232098 band -90859265. +-4744961 = -13232098 bor -90859265. +94601441 = -13232098 bxor -90859265. +-125172732 = -91617588 band -123781867. +-90226723 = -91617588 bor -123781867. +34946009 = -91617588 bxor -123781867. +19169290 = 61315114 band -113981925. +-71836101 = 61315114 bor -113981925. +-91005391 = 61315114 bxor -113981925. +8552848 = 62309304 band -54291055. +-534599 = 62309304 bor -54291055. +-9087447 = 62309304 bxor -54291055. +97454326 = 100601078 band -3168009. +-21257 = 100601078 bor -3168009. +-97475583 = 100601078 bxor -3168009. +82862404 = 116417380 band 100334029. +133889005 = 116417380 bor 100334029. +51026601 = 116417380 bxor 100334029. +92471426 = 92734082 band -3416685. +-3154029 = 92734082 bor -3416685. +-95625455 = 92734082 bxor -3416685. +-100515392 = -100511280 band -20290103. +-20285991 = -100511280 bor -20290103. +80229401 = -100511280 bxor -20290103. +17073358 = -106511154 band 21807087. +-101777425 = -106511154 bor 21807087. +-118850783 = -106511154 bxor 21807087. +33722500 = 33733372 band -83192443. +-83181571 = 33733372 bor -83192443. +-116904071 = 33733372 bxor -83192443. +5131274 = 116285402 band 21982219. +133136347 = 116285402 bor 21982219. +128005073 = 116285402 bxor 21982219. +-115081216 = -46232856 band -110885631. +-42037271 = -46232856 bor -110885631. +73043945 = -46232856 bxor -110885631. +8560038 = -119365722 band 92716519. +-35209241 = -119365722 bor 92716519. +-43769279 = -119365722 bxor 92716519. +8413204 = -1741420 band 9105469. +-1049155 = -1741420 bor 9105469. +-9462359 = -1741420 bxor 9105469. +8458242 = -58126286 band 32985475. +-33599053 = -58126286 bor 32985475. +-42057295 = -58126286 bxor 32985475. +70337280 = -9056512 band 70996793. +-8396999 = -9056512 bor 70996793. +-78734279 = -9056512 bxor 70996793. +68386910 = 129236350 band -61635873. +-786433 = 129236350 bor -61635873. +-69173343 = 129236350 bxor -61635873. +-119486172 = -118957268 band -34280971. +-33752067 = -118957268 bor -34280971. +85734105 = -118957268 bxor -34280971. +-117022326 = -116493430 band -115905029. +-115376133 = -116493430 bor -115905029. +1646193 = -116493430 bxor -115905029. +85340176 = -39944680 band 91697265. +-33587591 = -39944680 bor 91697265. +-118927767 = -39944680 bxor 91697265. +-60805546 = -51888554 band -26939689. +-18022697 = -51888554 bor -26939689. +42782849 = -51888554 bxor -26939689. +615044 = 50947012 band 83714733. +134046701 = 50947012 bor 83714733. +133431657 = 50947012 bxor 83714733. +8495458 = 46262754 band -123756173. +-85988877 = 46262754 bor -123756173. +-94484335 = 46262754 bxor -123756173. +18511904 = 18544688 band 87719081. +87751865 = 18544688 bor 87719081. +69239961 = 18544688 bxor 87719081. +-58146802 = -6766034 band -53943857. +-2563089 = -6766034 bor -53943857. +55583713 = -6766034 bxor -53943857. +-117104060 = -76585124 band -48940443. +-8421507 = -76585124 bor -48940443. +108682553 = -76585124 bxor -48940443. +9618218 = -118303942 band 77319147. +-50603013 = -118303942 bor 77319147. +-60221231 = -118303942 bxor 77319147. +18879808 = 20553032 band 19142625. +20815849 = 20553032 bor 19142625. +1936041 = 20553032 bxor 19142625. +2631942 = 78309638 band 6896583. +82574279 = 78309638 bor 6896583. +79942337 = 78309638 bxor 6896583. +-18267884 = -1096204 band -18263779. +-1092099 = -1096204 bor -18263779. +17175785 = -1096204 bxor -18263779. +-131035902 = -109277294 band -88879773. +-67121165 = -109277294 bor -88879773. +63914737 = -109277294 bxor -88879773. +75808768 = 78957920 band -3218919. +-69767 = 78957920 bor -3218919. +-75878535 = 78957920 bxor -3218919. +-134213474 = -61861154 band -108274497. +-35922177 = -61861154 bor -108274497. +98291297 = -61861154 bxor -108274497. +-125827452 = -125214836 band -1931563. +-1318947 = -125214836 bor -1931563. +124508505 = -125214836 bxor -1931563. +132298 = 105283306 band -106199589. +-1048581 = 105283306 bor -106199589. +-1180879 = 105283306 bxor -106199589. +1091664 = 53667960 band 72465233. +125041529 = 53667960 bor 72465233. +123949865 = 53667960 bxor 72465233. +-16743242 = -8020042 band -11361097. +-2637897 = -8020042 bor -11361097. +14105345 = -8020042 bxor -11361097. +10489860 = 15340580 band -39470195. +-34619475 = 15340580 bor -39470195. +-45109335 = 15340580 bxor -39470195. +-121634494 = -87817918 band -119351981. +-85535405 = -87817918 bor -119351981. +36099089 = -87817918 bxor -119351981. +8782464 = 113659536 band 29328265. +134205337 = 113659536 bor 29328265. +125422873 = 113659536 bxor 29328265. +-49257586 = -40570994 band -12880977. +-4194385 = -40570994 bor -12880977. +45063201 = -40570994 bxor -12880977. +25281284 = 32097212 band -107753659. +-100937731 = 32097212 bor -107753659. +-126219015 = 32097212 bxor -107753659. +22286986 = 24409754 band -2778165. +-655397 = 24409754 bor -2778165. +-22942383 = 24409754 bxor -2778165. +-64677248 = -43163736 band -22603071. +-1089559 = -43163736 bor -22603071. +63587689 = -43163736 bxor -22603071. +-125820890 = -107781530 band -56612441. +-38573081 = -107781530 bor -56612441. +87247809 = -107781530 bxor -56612441. +557140 = -83046828 band 71934461. +-11669507 = -83046828 bor 71934461. +-12226647 = -83046828 bxor 71934461. +-117229502 = -110936334 band -40126141. +-33832973 = -110936334 bor -40126141. +83396529 = -110936334 bxor -40126141. +-124624704 = -91063360 band -124559111. +-90997767 = -91063360 bor -124559111. +33626937 = -91063360 bxor -124559111. +2228254 = 132274238 band 3581599. +133627583 = 132274238 bor 3581599. +131399329 = 132274238 bxor 3581599. +-134212700 = -66874388 band -115338315. +-48000003 = -66874388 bor -115338315. +86212697 = -66874388 bxor -115338315. +2164746 = -72893878 band 6884795. +-68173829 = -72893878 bor 6884795. +-70338575 = -72893878 bxor 6884795. +8913424 = -125041960 band 126563889. +-7391495 = -125041960 bor 126563889. +-16304919 = -125041960 bxor 126563889. +58720278 = -72404714 band 126929559. +-4195433 = -72404714 bor 126929559. +-62915711 = -72404714 bxor 126929559. +-131595260 = -30772092 band -106167187. +-5344019 = -30772092 bor -106167187. +126251241 = -30772092 bxor -106167187. +346146 = 15026338 band -49448653. +-34768461 = 15026338 bor -49448653. +-35114607 = 15026338 bxor -49448653. +1069152 = -98806544 band 26311273. +-73564423 = -98806544 bor 26311273. +-74633575 = -98806544 bxor 26311273. +68174990 = 74665198 band 77362575. +83852783 = 74665198 bor 77362575. +15677793 = 74665198 bxor 77362575. +-133672956 = -32911332 band -113355739. +-12594115 = -32911332 bor -113355739. +121078841 = -32911332 bxor -113355739. +104876458 = 113986042 band 108321707. +117431291 = 113986042 bor 108321707. +12554833 = 113986042 bxor 108321707. +-98500608 = -68038136 band -31126111. +-663639 = -68038136 bor -31126111. +97836969 = -68038136 bxor -31126111. +-115342458 = -76280890 band -48003193. +-8941625 = -76280890 bor -48003193. +106400833 = -76280890 bxor -48003193. +4326036 = 81135284 band -127671587. +-50862339 = 81135284 bor -127671587. +-55188375 = 81135284 bxor -127671587. +84218882 = 93658706 band 86447395. +95887219 = 93658706 bor 86447395. +11668337 = 93658706 bxor 86447395. +51712 = 103209504 band -104804391. +-1646599 = 103209504 bor -104804391. +-1698311 = 103209504 bxor -104804391. +4374558 = 21155230 band -95690625. +-78909953 = 21155230 bor -95690625. +-83284511 = 21155230 bxor -95690625. +6623236 = 32471116 band 6656149. +32504029 = 32471116 bor 6656149. +25880793 = 32471116 bxor 6656149. +76023178 = 92939690 band -20445797. +-3529285 = 92939690 bor -20445797. +-79552463 = 92939690 bxor -20445797. +-113147632 = -37630664 band -111435503. +-35918535 = -37630664 bor -111435503. +77229097 = -37630664 bxor -111435503. +-132882314 = -79891850 band -132685705. +-79695241 = -79891850 bor -132685705. +53187073 = -79891850 bxor -132685705. +71304260 = 73565412 band -20431539. +-18170387 = 73565412 bor -20431539. +-89474647 = 73565412 bxor -20431539. +68517890 = 75350018 band -40399597. +-33567469 = 75350018 bor -40399597. +-102085359 = 75350018 bxor -40399597. +69206336 = 104139600 band -35102391. +-169127 = 104139600 bor -35102391. +-69375463 = 104139600 bxor -35102391. +246350 = 17553998 band 82044783. +99352431 = 17553998 bor 82044783. +99106081 = 17553998 bxor 82044783. +4491268 = 73895036 band 13420805. +82824573 = 73895036 bor 13420805. +78333305 = 73895036 bxor 13420805. +54593802 = -78688934 band 133270411. +-12325 = -78688934 bor 133270411. +-54606127 = -78688934 bxor 133270411. +47509504 = 48165992 band 131461249. +132117737 = 48165992 bor 131461249. +84608233 = 48165992 bxor 131461249. +2114854 = -98245338 band 15422823. +-84937369 = -98245338 bor 15422823. +-87052223 = -98245338 bxor 15422823. +-52428012 = -52236524 band -17820739. +-17629251 = -52236524 bor -17820739. +34798761 = -52236524 bxor -17820739. +55058690 = 57290162 band 130932995. +133164467 = 57290162 bor 130932995. +78105777 = 57290162 bxor 130932995. +-125228928 = -125179776 band -91279687. +-91230535 = -125179776 bor -91279687. +33998393 = -125179776 bxor -91279687. +-113180066 = -79072514 band -37516705. +-3409153 = -79072514 bor -37516705. +109770913 = -79072514 bxor -37516705. +6294564 = 82119852 band -127206027. +-51380739 = 82119852 bor -127206027. +-57675303 = 82119852 bxor -127206027. +4210954 = -62537462 band 37776763. +-28971653 = -62537462 bor 37776763. +-33182607 = -62537462 bxor 37776763. +-18332784 = -18069608 band -328719. +-65543 = -18069608 bor -328719. +18267241 = -18069608 bxor -328719. +67527254 = 67560406 band -35756457. +-35723305 = 67560406 bor -35756457. +-103250559 = 67560406 bxor -35756457. +-131972092 = -114670268 band -21862867. +-4561043 = -114670268 bor -21862867. +127411049 = -114670268 bxor -21862867. +14745698 = 15034210 band -17231629. +-16943117 = 15034210 bor -17231629. +-31688815 = 15034210 bxor -17231629. +36188192 = 36204976 band -67356631. +-67339847 = 36204976 bor -67356631. +-103528039 = 36204976 bxor -67356631. +67141902 = -63531090 band 67750223. +-62922769 = -63531090 bor 67750223. +-130064671 = -63531090 bxor 67750223. +9578692 = 94042332 band 16199141. +100662781 = 94042332 bor 16199141. +91084089 = 94042332 bxor 16199141. +-46104534 = -44531526 band -3953813. +-2380805 = -44531526 bor -3953813. +43723729 = -44531526 bxor -3953813. +71352896 = 72140488 band -933023. +-145431 = 72140488 bor -933023. +-71498327 = 72140488 bxor -933023. +7176710 = 25030278 band 49255239. +67108807 = 25030278 bor 49255239. +59932097 = 25030278 bxor 49255239. +109184020 = -20215948 band 128332957. +-1067011 = -20215948 bor 128332957. +-110251031 = -20215948 bxor 128332957. +527362 = 70937874 band -133686045. +-63275533 = 70937874 bor -133686045. +-63802895 = 70937874 bxor -133686045. +-32365440 = -19683616 band -29983335. +-17301511 = -19683616 bor -29983335. +15063929 = -19683616 bxor -29983335. +75759646 = 80627806 band -57301953. +-52433793 = 80627806 bor -57301953. +-128193439 = 80627806 bxor -57301953. +-77049852 = -75738868 band -1549739. +-238755 = -75738868 bor -1549739. +76811097 = -75738868 bxor -1549739. +67241034 = 70421610 band 71976283. +75156859 = 70421610 bor 71976283. +7915825 = 70421610 bxor 71976283. +69288144 = 69431800 band -39762223. +-39618567 = 69431800 bor -39762223. +-108906711 = 69431800 bxor -39762223. +29688886 = 132449590 band 31317047. +134077751 = 132449590 bor 31317047. +104388865 = 132449590 bxor 31317047. +100676868 = -31869532 band 119701261. +-12845139 = -31869532 bor 119701261. +-113522007 = -31869532 bxor 119701261. +18875586 = -42713406 band 27919571. +-33669421 = -42713406 bor 27919571. +-52545007 = -42713406 bxor 27919571. +17074176 = 17729552 band -50004215. +-49348839 = 17729552 bor -50004215. +-66423015 = 17729552 bxor -50004215. +33685774 = -87325426 band 33954607. +-87056593 = -87325426 bor 33954607. +-120742367 = -87325426 bxor 33954607. +104071172 = -29616836 band 108364485. +-25323523 = -29616836 bor 108364485. +-129394695 = -29616836 bxor 108364485. +86122506 = 121562138 band 90389323. +125828955 = 121562138 bor 90389323. +39706449 = 121562138 bxor 90389323. +101711872 = -28096216 band 112232001. +-17576087 = -28096216 bor 112232001. +-119287959 = -28096216 bxor 112232001. +-134217434 = -111728666 band -98025177. +-75536409 = -111728666 bor -98025177. +58681025 = -111728666 bxor -98025177. +36062548 = 36163540 band -29473411. +-29372419 = 36163540 bor -29473411. +-65434967 = 36163540 bxor -29473411. +72206402 = 90037362 band 72206531. +90037491 = 90037362 bor 72206531. +17831089 = 90037362 bxor 72206531. +34346048 = 35394880 band 65977465. +67026297 = 35394880 bor 65977465. +32680249 = 35394880 bxor 65977465. +11013150 = -123122242 band 79310367. +-54825025 = -123122242 bor 79310367. +-65838175 = -123122242 bxor 79310367. +328996 = -129153684 band 26584885. +-102897795 = -129153684 bor 26584885. +-103226791 = -129153684 bxor 26584885. +-133659382 = -39286838 band -94532293. +-159749 = -39286838 bor -94532293. +133499633 = -39286838 bxor -94532293. +393232 = 25119832 band 8815025. +33541625 = 25119832 bor 8815025. +33148393 = 25119832 bxor 8815025. +868886 = 78599830 band -116538857. +-38807913 = 78599830 bor -116538857. +-39676799 = 78599830 bxor -116538857. +12617220 = 13161988 band 30443501. +30988269 = 13161988 bor 30443501. +18371049 = 13161988 bxor 30443501. +147490 = -41794014 band 35809459. +-6132045 = -41794014 bor 35809459. +-6279535 = -41794014 bxor 35809459. +3802208 = 33508976 band -29706775. +-7 = 33508976 bor -29706775. +-3802215 = 33508976 bxor -29706775. +-125796338 = -39673234 band -86975217. +-852113 = -39673234 bor -86975217. +124944225 = -39673234 bxor -86975217. +14860676 = 115532188 band -100677723. +-6211 = 115532188 bor -100677723. +-14866887 = 115532188 bxor -100677723. +-62377174 = -10848390 band -62375125. +-10846341 = -10848390 bor -62375125. +51530833 = -10848390 bxor -62375125. +-133547776 = -83199096 band -129353439. +-79004759 = -83199096 bor -129353439. +54543017 = -83199096 bxor -129353439. +25694470 = 92836166 band -108175609. +-41033913 = 92836166 bor -108175609. +-66728383 = 92836166 bxor -108175609. +-100646892 = -91240396 band -93305251. +-83898755 = -91240396 bor -93305251. +16748137 = -91240396 bxor -93305251. +286850 = 2915282 band 118940835. +121569267 = 2915282 bor 118940835. +121282417 = 2915282 bxor 118940835. +107684608 = 125514656 band 116386649. +134216697 = 125514656 bor 116386649. +26532089 = 125514656 bxor 116386649. +2097950 = -38632674 band 2697215. +-38033409 = -38632674 bor 2697215. +-40131359 = -38632674 bxor 2697215. +2809860 = -101717556 band 69919765. +-34607651 = -101717556 bor 69919765. +-37417511 = -101717556 bxor 69919765. +82968842 = 83866410 band 99763483. +100661051 = 83866410 bor 99763483. +17692209 = 83866410 bxor 99763483. +33719440 = 119002808 band 48409745. +133693113 = 119002808 bor 48409745. +99973673 = 119002808 bxor 48409745. +69474294 = 71161846 band 73799671. +75487223 = 71161846 bor 73799671. +6012929 = 71161846 bxor 73799671. +4489284 = -87054748 band 74744013. +-16800019 = -87054748 bor 74744013. +-21289303 = -87054748 bxor 74744013. +4340866 = 6782338 band -119915373. +-117473901 = 6782338 bor -119915373. +-121814767 = 6782338 bxor -119915373. +1066176 = 1230032 band -120234807. +-120070951 = 1230032 bor -120234807. +-121137127 = 1230032 bxor -120234807. +134862 = 26472398 band 107089647. +133427183 = 26472398 bor 107089647. +133292321 = 26472398 bxor 107089647. +351364 = 69688828 band 5110917. +74448381 = 69688828 bor 5110917. +74097017 = 69688828 bxor 5110917. +141834 = -134006054 band 65710859. +-68437029 = -134006054 bor 65710859. +-68578863 = -134006054 bxor 65710859. +8543232 = 9068008 band -50930687. +-50405911 = 9068008 bor -50930687. +-58949143 = 9068008 bxor -50930687. +141478 = 99232422 band 1502439. +100593383 = 99232422 bor 1502439. +100451905 = 99232422 bxor 1502439. +126890004 = 127627412 band -772291. +-34883 = 127627412 bor -772291. +-126924887 = 127627412 bxor -772291. +14303234 = -100775118 band 115044483. +-33869 = -100775118 bor 115044483. +-14337103 = -100775118 bxor 115044483. +512 = 590336 band -26080711. +-25490887 = 590336 bor -26080711. +-25491399 = 590336 bxor -26080711. +79724638 = 113371262 band 81433055. +115079679 = 113371262 bor 81433055. +35355041 = 113371262 bxor 81433055. +-94367708 = -84132308 band -94367499. +-84132099 = -84132308 bor -94367499. +10235609 = -84132308 bxor -94367499. +8391818 = 42995338 band 75525371. +110128891 = 42995338 bor 75525371. +101737073 = 42995338 bxor 75525371. +327952 = 17109272 band -85080207. +-68298887 = 17109272 bor -85080207. +-68626839 = 17109272 bxor -85080207. +4753750 = -60257962 band 14605783. +-50405929 = -60257962 bor 14605783. +-55159679 = -60257962 bxor 14605783. +12984452 = 29763268 band 13003181. +29781997 = 29763268 bor 13003181. +16797545 = 29763268 bxor 13003181. +4816994 = 24896738 band -95846285. +-75766541 = 24896738 bor -95846285. +-80583535 = 24896738 bxor -95846285. +33612576 = 39906096 band 34403241. +40696761 = 39906096 bor 34403241. +7084185 = 39906096 bxor 34403241. +-130998258 = -8950482 band -122572593. +-524817 = -8950482 bor -122572593. +130473441 = -8950482 bxor -122572593. +33554500 = 111250012 band -99081883. +-21386371 = 111250012 bor -99081883. +-54940871 = 111250012 bxor -99081883. +125831722 = -7262662 band 130190059. +-2904325 = -7262662 bor 130190059. +-128736047 = -7262662 bxor 130190059. +15360064 = 15396936 band -118591775. +-118554903 = 15396936 bor -118591775. +-133914967 = 15396936 bxor -118591775. +1105926 = 106165254 band -121836857. +-16777529 = 106165254 bor -121836857. +-17883455 = 106165254 bxor -121836857. +75630612 = 81971444 band -25028579. +-18687747 = 81971444 bor -25028579. +-94318359 = 81971444 bxor -25028579. +67323906 = 69946002 band 101936227. +104558323 = 69946002 bor 101936227. +37234417 = 69946002 bxor 101936227. +-124977152 = -119701408 band -38987495. +-33711751 = -119701408 bor -38987495. +91265401 = -119701408 bxor -38987495. +8808862 = 45055454 band 80112575. +116359167 = 45055454 bor 80112575. +107550305 = 45055454 bxor 80112575. +34078852 = 34226828 band 49098197. +49246173 = 34226828 bor 49098197. +15167321 = 34226828 bxor 49098197. +-92274486 = -89024022 band -8387365. +-5136901 = -89024022 bor -8387365. +87137585 = -89024022 bxor -8387365. +39768656 = 123665272 band -85994927. +-2098311 = 123665272 bor -85994927. +-41866967 = 123665272 bxor -85994927. +117441206 = -16291146 band 124785591. +-8946761 = -16291146 bor 124785591. +-126387967 = -16291146 bxor 124785591. +71582212 = 121919268 band 75383437. +125720493 = 121919268 bor 75383437. +54138281 = 121919268 bxor 75383437. +13378 = -132678590 band 115881043. +-16810925 = -132678590 bor 115881043. +-16824303 = -132678590 bxor 115881043. +-134135680 = -66993776 band -82216311. +-15074407 = -66993776 bor -82216311. +119061273 = -66993776 bxor -82216311. +2425486 = -64677234 band 28820143. +-38282577 = -64677234 bor 28820143. +-40708063 = -64677234 bxor 28820143. +9732 = -85367108 band 68564549. +-16812291 = -85367108 bor 68564549. +-16822023 = -85367108 bxor 68564549. +4477066 = 6050202 band -12068149. +-10495013 = 6050202 bor -12068149. +-14972079 = 6050202 bxor -12068149. +-130011008 = -96193880 band -60231231. +-26414103 = -96193880 bor -60231231. +103596905 = -96193880 bxor -60231231. diff --git a/erts/emulator/test/big_SUITE_data/eq_32.dat b/erts/emulator/test/big_SUITE_data/eq_32.dat new file mode 100644 index 0000000000..e7118ccdde --- /dev/null +++ b/erts/emulator/test/big_SUITE_data/eq_32.dat @@ -0,0 +1,3000 @@ +1082131525 = 1621645175 band 1154714701. +1694228351 = 1621645175 bor 1154714701. +612096826 = 1621645175 bxor 1154714701. +46178305 = 599847955 band 182034505. +735704155 = 599847955 bor 182034505. +689525850 = 599847955 bxor 182034505. +-1055868923 = -507724177 band -988612603. +-440467857 = -507724177 bor -988612603. +615401066 = -507724177 bxor -988612603. +-1962933631 = -1358900597 band -1949298815. +-1345265781 = -1358900597 bor -1949298815. +617667850 = -1358900597 bxor -1949298815. +1093140517 = 1730677863 band 1106059965. +1743597311 = 1730677863 bor 1106059965. +650456794 = 1730677863 bxor 1106059965. +9308161 = 715065347 band 30289337. +736046523 = 715065347 bor 30289337. +726738362 = 715065347 bxor 30289337. +-905961387 = -369090209 band -837096331. +-300225153 = -369090209 bor -837096331. +605736234 = -369090209 bxor -837096331. +-2111156111 = -1422953349 band -2110072079. +-1421869317 = -1422953349 bor -2110072079. +689286794 = -1422953349 bxor -2110072079. +1141904645 = 1681317207 band 1318139181. +1857551743 = 1681317207 bor 1318139181. +715647098 = 1681317207 bxor 1318139181. +73463585 = 669120499 band 209254185. +804911099 = 669120499 bor 209254185. +731447514 = 669120499 bxor 209254185. +-1073741755 = -535158705 band -973021979. +-434438929 = -535158705 bor -973021979. +639302826 = -535158705 bxor -973021979. +-2147327391 = -1576897941 band -1922604447. +-1352174997 = -1576897941 bor -1922604447. +795152394 = -1576897941 bxor -1922604447. +1079165445 = 1741933127 band 1079427997. +1742195679 = 1741933127 bor 1079427997. +663030234 = 1741933127 bxor 1079427997. +6340737 = 746111971 band 48299161. +788070395 = 746111971 bor 48299161. +781729658 = 746111971 bxor 48299161. +-1003910891 = -454444225 band -834942635. +-285475969 = -454444225 bor -834942635. +718434922 = -454444225 bxor -834942635. +-2096593839 = -1555510181 band -1891850799. +-1350767141 = -1555510181 bor -1891850799. +745826698 = -1555510181 bxor -1891850799. +1083490821 = 1874711351 band 1083493901. +1874714431 = 1874711351 bor 1083493901. +791223610 = 1874711351 bxor 1083493901. +10753 = 588409811 band 214777353. +803176411 = 588409811 bor 214777353. +803165658 = 588409811 bxor 214777353. +-1006587899 = -284298705 band -1006456379. +-284167185 = -284298705 bor -1006456379. +722420714 = -284298705 bxor -1006456379. +-2147385279 = -1601076661 band -2124307135. +-1577998517 = -1601076661 bor -2124307135. +569386762 = -1601076661 bxor -2124307135. +1147293733 = 1735653415 band 1281512573. +1869872255 = 1735653415 bor 1281512573. +722578522 = 1735653415 bxor 1281512573. +305985 = 538832835 band 29670265. +568197115 = 538832835 bor 29670265. +567891130 = 538832835 bxor 29670265. +-1069251563 = -354040545 band -1068722635. +-353511617 = -354040545 bor -1068722635. +715739946 = -354040545 bxor -1068722635. +-2060910543 = -1389652933 band -2059575119. +-1388317509 = -1389652933 bor -2059575119. +672593034 = -1389652933 bxor -2059575119. +1075056645 = 1748318487 band 1150703341. +1823965183 = 1748318487 bor 1150703341. +748908538 = 1748318487 bxor 1150703341. +17450145 = 566906803 band 151942377. +701399035 = 566906803 bor 151942377. +683948890 = 566906803 bxor 151942377. +-1030736891 = -359648241 band -942639451. +-271550801 = -359648241 bor -942639451. +759186090 = -359648241 bxor -942639451. +-2111438815 = -1373240789 band -2080974815. +-1342776789 = -1373240789 bor -2080974815. +768662026 = -1373240789 bxor -2080974815. +1224774661 = 1761646087 band 1304941917. +1841813343 = 1761646087 bor 1304941917. +617038682 = 1761646087 bxor 1304941917. +2561 = 537299875 band 162622041. +699919355 = 537299875 bor 162622041. +699916794 = 537299875 bxor 162622041. +-1056697835 = -437502209 band -888843499. +-269647873 = -437502209 bor -888843499. +787049962 = -437502209 bxor -888843499. +-1975187439 = -1437610981 band -1904931951. +-1367355493 = -1437610981 bor -1904931951. +607831946 = -1437610981 bxor -1904931951. +1074073285 = 1855262455 band 1078841293. +1860030463 = 1855262455 bor 1078841293. +785957178 = 1855262455 bxor 1078841293. +134251393 = 746693523 band 175414217. +787856347 = 746693523 bor 175414217. +653604954 = 746693523 bxor 175414217. +-1040178811 = -359078417 band -970839163. +-289738769 = -359078417 bor -970839163. +750440042 = -359078417 bxor -970839163. +-2011762175 = -1439174133 band -1923155199. +-1350567157 = -1439174133 bor -1923155199. +661195018 = -1439174133 bxor -1923155199. +1211171365 = 1802609639 band 1212106301. +1803544575 = 1802609639 bor 1212106301. +592373210 = 1802609639 bxor 1212106301. +9044225 = 581605251 band 31394105. +603955131 = 581605251 bor 31394105. +594910906 = 581605251 bxor 31394105. +-1055577899 = -336254753 band -1054998539. +-335675393 = -336254753 bor -1054998539. +719902506 = -336254753 bxor -1054998539. +-2146885007 = -1473416197 band -2128894351. +-1455425541 = -1473416197 bor -2128894351. +691459466 = -1473416197 bxor -2128894351. +1162940549 = 1876251863 band 1165179053. +1878490367 = 1876251863 bor 1165179053. +715549818 = 1876251863 bxor 1165179053. +103817761 = 665872243 band 104313513. +666367995 = 665872243 bor 104313513. +562550234 = 665872243 bxor 104313513. +-1021312955 = -484440113 band -810561435. +-273688593 = -484440113 bor -810561435. +747624362 = -484440113 bxor -810561435. +-2146303519 = -1606462997 band -2116940319. +-1577099797 = -1606462997 bor -2116940319. +569203722 = -1606462997 bxor -2116940319. +1233133829 = 1774133703 band 1266722589. +1807722463 = 1774133703 bor 1266722589. +574588634 = 1774133703 bxor 1266722589. +142610433 = 713167715 band 226859033. +797416315 = 713167715 bor 226859033. +654805882 = 713167715 bxor 226859033. +-1068990315 = -285703489 band -1051812651. +-268525825 = -285703489 bor -1051812651. +800464490 = -285703489 bxor -1051812651. +-2144861871 = -1606644773 band -1888931503. +-1350714405 = -1606644773 bor -1888931503. +794147466 = -1606644773 bxor -1888931503. +1085145221 = 1693321911 band 1103008141. +1711184831 = 1693321911 bor 1103008141. +626039610 = 1693321911 bxor 1103008141. +26122497 = 600742739 band 227522953. +802143195 = 600742739 bor 227522953. +776020698 = 600742739 bxor 227522953. +-1072627451 = -467822161 band -1053727419. +-448922129 = -467822161 bor -1053727419. +623705322 = -467822161 bxor -1053727419. +-2122317631 = -1481367093 band -2121789247. +-1480838709 = -1481367093 bor -2121789247. +641478922 = -1481367093 bxor -2121789247. +1111558053 = 1793134503 band 1128527869. +1810104319 = 1793134503 bor 1128527869. +698546266 = 1793134503 bxor 1128527869. +33822273 = 637861699 band 199038713. +803078139 = 637861699 bor 199038713. +769255866 = 637861699 bxor 199038713. +-1001518955 = -319927137 band -967890507. +-286298689 = -319927137 bor -967890507. +715220266 = -319927137 bxor -967890507. +-2020278223 = -1477110853 band -2020234191. +-1477066821 = -1477110853 bor -2020234191. +543211402 = -1477110853 bxor -2020234191. +1120342021 = 1658269847 band 1323817581. +1861745407 = 1658269847 bor 1323817581. +741403386 = 1658269847 bxor 1323817581. +219426849 = 760495923 band 229945449. +771014523 = 760495923 bor 229945449. +551587674 = 760495923 bxor 229945449. +-1056404987 = -376857713 band -1017189851. +-337642577 = -376857713 bor -1017189851. +718762410 = -376857713 bxor -1017189851. +-2146958943 = -1542561365 band -2001140831. +-1396743253 = -1542561365 bor -2001140831. +750215690 = -1542561365 bxor -2001140831. +1094789253 = 1640983943 band 1195456733. +1741651423 = 1640983943 bor 1195456733. +646862170 = 1640983943 bxor 1195456733. +134807809 = 799759139 band 136152537. +801103867 = 799759139 bor 136152537. +666296058 = 799759139 bxor 136152537. +-960068075 = -271677825 band -958945643. +-270555393 = -271677825 bor -958945643. +689512682 = -271677825 bxor -958945643. +-2134310127 = -1597043813 band -2082924783. +-1545658469 = -1597043813 bor -2082924783. +588651658 = -1597043813 bxor -2082924783. +1115685445 = 1787348599 band 1118245709. +1789908863 = 1787348599 bor 1118245709. +674223418 = 1787348599 bxor 1118245709. +211292929 = 750342931 band 266245961. +805295963 = 750342931 bor 266245961. +594003034 = 750342931 bxor 266245961. +-900723451 = -346288785 band -890216699. +-335782033 = -346288785 bor -890216699. +564941418 = -346288785 bxor -890216699. +-2071723903 = -1530523253 band -1885542783. +-1344342133 = -1530523253 bor -1885542783. +727381770 = -1530523253 bxor -1885542783. +1224747301 = 1837251431 band 1261463997. +1873968127 = 1837251431 bor 1261463997. +649220826 = 1837251431 bxor 1261463997. +158082049 = 770516739 band 159311033. +771745723 = 770516739 bor 159311033. +613663674 = 770516739 bxor 159311033. +-981462955 = -309252001 band -979365003. +-307154049 = -309252001 bor -979365003. +674308906 = -309252001 bxor -979365003. +-2008911503 = -1472040069 band -1972669967. +-1435798533 = -1472040069 bor -1972669967. +573112970 = -1472040069 bxor -1972669967. +1219496965 = 1761266775 band 1320434733. +1862204543 = 1761266775 bor 1320434733. +642707578 = 1761266775 bxor 1320434733. +4539937 = 645256947 band 155545129. +796262139 = 645256947 bor 155545129. +791722202 = 645256947 bxor 155545129. +-930299067 = -309530801 band -929184795. +-308416529 = -309530801 bor -929184795. +621882538 = -309530801 bxor -929184795. +-2143080095 = -1521274517 band -1972651679. +-1350846101 = -1521274517 bor -1972651679. +792233994 = -1521274517 bxor -1972651679. +1220610053 = 1760655687 band 1321831069. +1861876703 = 1760655687 bor 1321831069. +641266650 = 1760655687 bxor 1321831069. +50340481 = 591553251 band 54080409. +595293179 = 591553251 bor 54080409. +544952698 = 591553251 bxor 54080409. +-1071628267 = -399619521 band -1050644395. +-378635649 = -399619521 bor -1050644395. +692992618 = -399619521 bxor -1050644395. +-2054944687 = -1480111269 band -1920680751. +-1345847333 = -1480111269 bor -1920680751. +709097354 = -1480111269 bxor -1920680751. +1074085893 = 1730495031 band 1086805261. +1743214399 = 1730495031 bor 1086805261. +669128506 = 1730495031 bxor 1086805261. +184614913 = 721537747 band 186725641. +723648475 = 721537747 bor 186725641. +539033562 = 721537747 bxor 186725641. +-1072431099 = -535543505 band -920708923. +-383821329 = -535543505 bor -920708923. +688609770 = -535543505 bxor -920708923. +-1995620287 = -1389510325 band -1990362047. +-1384252085 = -1389510325 bor -1990362047. +611368202 = -1389510325 bxor -1990362047. +1224999717 = 1796548391 band 1304730493. +1876279167 = 1796548391 bor 1304730493. +651279450 = 1796548391 bxor 1304730493. +67109441 = 774049475 band 75788921. +782728955 = 774049475 bor 75788921. +715619514 = 774049475 bxor 75788921. +-997157867 = -308423649 band -992953035. +-304218817 = -308423649 bor -992953035. +692939050 = -308423649 bxor -992953035. +-2141940943 = -1529507013 band -1956841551. +-1344407621 = -1529507013 bor -1956841551. +797533322 = -1529507013 bxor -1956841551. +1107298309 = 1778395159 band 1117281773. +1788378623 = 1778395159 bor 1117281773. +681080314 = 1778395159 bxor 1117281773. +42019489 = 651505331 band 44690409. +654176251 = 651505331 bor 44690409. +612156762 = 651505331 bxor 44690409. +-1004011259 = -286653681 band -986948187. +-269590609 = -286653681 bor -986948187. +734420650 = -286653681 bxor -986948187. +-2004352735 = -1345470165 band -2002112735. +-1343230165 = -1345470165 bor -2002112735. +661122570 = -1345470165 bxor -2002112735. +1187054597 = 1726301447 band 1339661405. +1878908255 = 1726301447 bor 1339661405. +691853658 = 1726301447 bxor 1339661405. +134225921 = 688335523 band 144220505. +698330107 = 688335523 bor 144220505. +564104186 = 688335523 bxor 144220505. +-964638699 = -405287425 band -962004459. +-402653185 = -405287425 bor -962004459. +561985514 = -405287425 bxor -962004459. +-2145123823 = -1595585765 band -1909710191. +-1360172133 = -1595585765 bor -1909710191. +784951690 = -1595585765 bxor -1909710191. +1082348741 = 1652784631 band 1239373517. +1809809407 = 1652784631 bor 1239373517. +727460666 = 1652784631 bxor 1239373517. +641 = 577241747 band 152539849. +729780955 = 577241747 bor 152539849. +729780314 = 577241747 bxor 152539849. +-1073475451 = -502909713 band -1048735099. +-478169361 = -502909713 bor -1048735099. +595306090 = -502909713 bxor -1048735099. +-2138501119 = -1398066933 band -2138451455. +-1398017269 = -1398066933 bor -2138451455. +740483850 = -1398066933 bxor -2138451455. +1212186661 = 1801048807 band 1220578621. +1809440767 = 1801048807 bor 1220578621. +597254106 = 1801048807 bxor 1220578621. +35946497 = 711374467 band 112050233. +787478203 = 711374467 bor 112050233. +751531706 = 711374467 bxor 112050233. +-931125547 = -321636385 band -912185611. +-302696449 = -321636385 bor -912185611. +628429098 = -321636385 bxor -912185611. +-2010501007 = -1452379397 band -1943388815. +-1385267205 = -1452379397 bor -1943388815. +625233802 = -1452379397 bxor -1943388815. +1208222597 = 1839678423 band 1213480877. +1844936703 = 1839678423 bor 1213480877. +636714106 = 1839678423 bxor 1213480877. +35782689 = 573720179 band 60959145. +598896635 = 573720179 bor 60959145. +563113946 = 573720179 bxor 60959145. +-868182459 = -312420657 band -825575579. +-269813777 = -312420657 bor -825575579. +598368682 = -312420657 bxor -825575579. +-2060189471 = -1354886933 band -2060163871. +-1354861333 = -1354886933 bor -2060163871. +705328138 = -1354886933 bxor -2060163871. +1075855365 = 1667944647 band 1211199005. +1803288287 = 1667944647 bor 1211199005. +727432922 = 1667944647 bxor 1211199005. +12157441 = 616149603 band 33279769. +637271931 = 616149603 bor 33279769. +625114490 = 616149603 bxor 33279769. +-872349291 = -292875841 band -864992299. +-285518849 = -292875841 bor -864992299. +586830442 = -292875841 bxor -864992299. +-2021062575 = -1477899557 band -2020652975. +-1477489957 = -1477899557 bor -2020652975. +543572618 = -1477899557 bxor -2020652975. +1076041861 = 1684240823 band 1269766285. +1877965247 = 1684240823 bor 1269766285. +801923386 = 1684240823 bxor 1269766285. +42053633 = 648804947 band 58830985. +665582299 = 648804947 bor 58830985. +623528666 = 648804947 bxor 58830985. +-1061042171 = -521017169 band -909390779. +-369365777 = -521017169 bor -909390779. +691676394 = -521017169 bxor -909390779. +-2032115519 = -1359060789 band -2032015423. +-1358960693 = -1359060789 bor -2032015423. +673154826 = -1359060789 bxor -2032015423. +1073757861 = 1712340647 band 1239695101. +1878277887 = 1712340647 bor 1239695101. +804520026 = 1712340647 bxor 1239695101. +3673153 = 645406275 band 163237369. +804970491 = 645406275 bor 163237369. +801297338 = 645406275 bxor 163237369. +-925871979 = -353084513 band -909029195. +-336241729 = -353084513 bor -909029195. +589630250 = -353084513 bxor -909029195. +-2139028943 = -1580395845 band -1902951631. +-1344318533 = -1580395845 bor -1902951631. +794710410 = -1580395845 bxor -1902951631. +1235222789 = 1806704535 band 1302847853. +1874329599 = 1806704535 bor 1302847853. +639106810 = 1806704535 bxor 1302847853. +72091169 = 743251507 band 99493737. +770654075 = 743251507 bor 99493737. +698562906 = 743251507 bxor 99493737. +-936361979 = -391026033 band -885468891. +-340132945 = -391026033 bor -885468891. +596229034 = -391026033 bxor -885468891. +-2126511967 = -1352392533 band -2117444959. +-1343325525 = -1352392533 bor -2117444959. +783186442 = -1352392533 bxor -2117444959. +1140857989 = 1715608711 band 1167130589. +1741881311 = 1715608711 bor 1167130589. +601023322 = 1715608711 bxor 1167130589. +134264833 = 706345507 band 153271513. +725352187 = 706345507 bor 153271513. +591087354 = 706345507 bxor 153271513. +-938998507 = -335014529 band -931574379. +-327590401 = -335014529 bor -931574379. +611408106 = -335014529 bxor -931574379. +-2013132271 = -1466791269 band -1955713519. +-1409372517 = -1466791269 bor -1955713519. +603759754 = -1466791269 bxor -1955713519. +1082396741 = 1686451575 band 1140234829. +1744289663 = 1686451575 bor 1140234829. +661892922 = 1686451575 bxor 1140234829. +885249 = 730706451 band 69176905. +798998107 = 730706451 bor 69176905. +798112858 = 730706451 bxor 69176905. +-998161403 = -325624721 band -943077883. +-270541201 = -325624721 bor -943077883. +727620202 = -325624721 bxor -943077883. +-1910173567 = -1343795061 band -1910129279. +-1343750773 = -1343795061 bor -1910129279. +566422794 = -1343795061 bxor -1910129279. +1122508837 = 1660447335 band 1324331197. +1862269695 = 1660447335 bor 1324331197. +739760858 = 1660447335 bxor 1324331197. +100860417 = 639059459 band 124492729. +662691771 = 639059459 bor 124492729. +561831354 = 639059459 bxor 124492729. +-1021298091 = -406962337 band -887014795. +-272679041 = -406962337 bor -887014795. +748619050 = -406962337 bxor -887014795. +-2146434959 = -1447988613 band -2074605327. +-1376158981 = -1447988613 bor -2074605327. +770275978 = -1447988613 bxor -2074605327. +1079116549 = 1809496919 band 1079198509. +1809578879 = 1809496919 bor 1079198509. +730462330 = 1809496919 bxor 1079198509. +4564257 = 686142963 band 55436585. +737015291 = 686142963 bor 55436585. +732451034 = 686142963 bxor 55436585. +-1072518587 = -526664113 band -1070159131. +-524304657 = -526664113 bor -1070159131. +548213930 = -526664113 bxor -1070159131. +-2144595871 = -1409290133 band -2144595871. +-1409290133 = -1409290133 bor -2144595871. +735305738 = -1409290133 bxor -2144595871. +1160249349 = 1730881607 band 1169707421. +1740339679 = 1730881607 bor 1169707421. +580090330 = 1730881607 bxor 1169707421. +80216193 = 753402339 band 130902681. +804088827 = 753402339 bor 130902681. +723872634 = 753402339 bxor 130902681. +-1073737451 = -535897793 band -1065281707. +-527442049 = -535897793 bor -1065281707. +546295402 = -535897793 bxor -1065281707. +-1971273135 = -1365128613 band -1953967151. +-1347822629 = -1365128613 bor -1953967151. +623450506 = -1365128613 bxor -1953967151. +1075875845 = 1789440311 band 1081465869. +1795030335 = 1789440311 bor 1081465869. +719154490 = 1789440311 bxor 1081465869. +75573249 = 617425363 band 78720009. +620572123 = 617425363 bor 78720009. +544998874 = 617425363 bxor 78720009. +-1070198779 = -457797585 band -1053327419. +-440926225 = -457797585 bor -1053327419. +629272554 = -457797585 bxor -1053327419. +-2013003711 = -1423572917 band -2011868351. +-1422437557 = -1423572917 bor -2011868351. +590566154 = -1423572917 bxor -2011868351. +1099055653 = 1775392295 band 1168302717. +1844639359 = 1775392295 bor 1168302717. +745583706 = 1775392295 bxor 1168302717. +151005505 = 755248579 band 159394169. +763637243 = 755248579 bor 159394169. +612631738 = 755248579 bxor 159394169. +-1034887147 = -487464161 band -1018108875. +-470685889 = -487464161 bor -1018108875. +564201258 = -487464161 bxor -1018108875. +-1944550863 = -1394896325 band -1892118863. +-1342464325 = -1394896325 bor -1892118863. +602086538 = -1394896325 bxor -1892118863. +1141244933 = 1709643543 band 1310090477. +1878489087 = 1709643543 bor 1310090477. +737244154 = 1709643543 bxor 1310090477. +25165985 = 733744563 band 92365545. +800944123 = 733744563 bor 92365545. +775778138 = 733744563 bxor 92365545. +-1065074683 = -455093745 band -1014741851. +-404760913 = -455093745 bor -1014741851. +660313770 = -455093745 bxor -1014741851. +-2146336735 = -1596882901 band -2112256479. +-1562802645 = -1596882901 bor -2112256479. +583534090 = -1596882901 bxor -2112256479. +1147494405 = 1843786759 band 1181180765. +1877473119 = 1843786759 bor 1181180765. +729978714 = 1843786759 bxor 1181180765. +10733569 = 551799203 band 129751129. +670816763 = 551799203 bor 129751129. +660083194 = 551799203 bxor 129751129. +-901251051 = -362849025 band -901209835. +-362807809 = -362849025 bor -901209835. +538443242 = -362849025 bxor -901209835. +-2120873967 = -1512650213 band -1986053743. +-1377829989 = -1512650213 bor -1986053743. +743043978 = -1512650213 bxor -1986053743. +1317850309 = 1854794999 band 1324146125. +1861090815 = 1854794999 bor 1324146125. +543240506 = 1854794999 bxor 1324146125. +102891905 = 640311699 band 251038153. +788457947 = 640311699 bor 251038153. +685566042 = 640311699 bxor 251038153. +-922451579 = -384859153 band -875234939. +-337642513 = -384859153 bor -875234939. +584809066 = -384859153 bxor -875234939. +-2073026559 = -1401262069 band -2039437055. +-1367672565 = -1401262069 bor -2039437055. +705353994 = -1401262069 bxor -2039437055. +1109131301 = 1650328039 band 1270731837. +1811928575 = 1650328039 bor 1270731837. +702797274 = 1650328039 bxor 1270731837. +146298113 = 788452739 band 163084089. +805238715 = 788452739 bor 163084089. +658940602 = 788452739 bxor 163084089. +-939506475 = -330348833 band -937406987. +-328249345 = -330348833 bor -937406987. +611257130 = -330348833 bxor -937406987. +-2147463055 = -1492422149 band -2131438479. +-1476397573 = -1492422149 bor -2131438479. +671065482 = -1492422149 bxor -2131438479. +1083245189 = 1637167831 band 1152468653. +1706391295 = 1637167831 bor 1152468653. +623146106 = 1637167831 bxor 1152468653. +8225 = 680535411 band 105423017. +785950203 = 680535411 bor 105423017. +785941978 = 680535411 bxor 105423017. +-1071545275 = -448944689 band -891183515. +-268582929 = -448944689 bor -891183515. +802962346 = -448944689 bxor -891183515. +-1995404319 = -1449603093 band -1991066655. +-1445265429 = -1449603093 bor -1991066655. +550138890 = -1449603093 bxor -1991066655. +1074935045 = 1647476679 band 1163801885. +1736343519 = 1647476679 bor 1163801885. +661408474 = 1647476679 bxor 1163801885. +9175041 = 701321571 band 44959257. +737105787 = 701321571 bor 44959257. +727930746 = 701321571 bxor 44959257. +-896950123 = -356933441 band -879760683. +-339744001 = -356933441 bor -879760683. +557206122 = -356933441 bxor -879760683. +-2123298479 = -1443788325 band -2022613167. +-1343103013 = -1443788325 bor -2022613167. +780195466 = -1443788325 bxor -2022613167. +1158711429 = 1744103607 band 1293655949. +1879048127 = 1744103607 bor 1293655949. +720336698 = 1744103607 bxor 1293655949. +2425089 = 593844563 band 212838281. +804257755 = 593844563 bor 212838281. +801832666 = 593844563 bxor 212838281. +-916311291 = -379439185 band -849202363. +-312330257 = -379439185 bor -849202363. +603981034 = -379439185 bxor -849202363. +-1968922943 = -1348165685 band -1963475263. +-1342718005 = -1348165685 bor -1963475263. +626204938 = -1348165685 bxor -1963475263. +1140852133 = 1683713447 band 1325434365. +1868295679 = 1683713447 bor 1325434365. +727443546 = 1683713447 bxor 1325434365. +29623361 = 801586499 band 30704889. +802668027 = 801586499 bor 30704889. +773044666 = 801586499 bxor 30704889. +-1022991723 = -476681569 band -816875595. +-270565441 = -476681569 bor -816875595. +752426282 = -476681569 bxor -816875595. +-2147479503 = -1543433797 band -1957897679. +-1353851973 = -1543433797 bor -1957897679. +793627530 = -1543433797 bxor -1957897679. +1084295173 = 1722093207 band 1105455213. +1743253247 = 1722093207 bor 1105455213. +658958074 = 1722093207 bxor 1105455213. +52534305 = 589430067 band 258186857. +795082619 = 589430067 bor 258186857. +742548314 = 589430067 bxor 258186857. +-1073465339 = -512411249 band -871450587. +-310396497 = -512411249 bor -871450587. +763068842 = -512411249 bxor -871450587. +-2112515679 = -1575624789 band -2020101727. +-1483210837 = -1575624789 bor -2020101727. +629304842 = -1575624789 bxor -2020101727. +1079034501 = 1808845703 band 1079822045. +1809633247 = 1808845703 bor 1079822045. +730598746 = 1808845703 bxor 1079822045. +39883009 = 728013091 band 40104921. +728235003 = 728013091 bor 40104921. +688351994 = 728013091 bxor 40104921. +-1072389099 = -522345345 band -904465259. +-354421505 = -522345345 bor -904465259. +717967594 = -522345345 bxor -904465259. +-2035154671 = -1498281573 band -2034285295. +-1497412197 = -1498281573 bor -2034285295. +537742474 = -1498281573 bxor -2034285295. +1216356421 = 1855825015 band 1220682061. +1860150655 = 1855825015 bor 1220682061. +643794234 = 1855825015 bxor 1220682061. +1835265 = 540938515 band 127698249. +666801499 = 540938515 bor 127698249. +664966234 = 540938515 bxor 127698249. +-1056036603 = -445731985 band -878760699. +-268456081 = -445731985 bor -878760699. +787580522 = -445731985 bxor -878760699. +-2141158271 = -1604022389 band -2023058303. +-1485922421 = -1604022389 bor -2023058303. +655235850 = -1604022389 bxor -2023058303. +1158320421 = 1737136487 band 1294661565. +1873477631 = 1737136487 bor 1294661565. +715157210 = 1737136487 bxor 1294661565. +51658753 = 589128963 band 194269881. +731740091 = 589128963 bor 194269881. +680081338 = 589128963 bxor 194269881. +-930725803 = -393785761 band -828481163. +-291541121 = -393785761 bor -828481163. +639184682 = -393785761 bxor -828481163. +-2147479183 = -1350798981 band -2147442703. +-1350762501 = -1350798981 bor -2147442703. +796716682 = -1350798981 bxor -2147442703. +1078331909 = 1826007639 band 1131301421. +1878977151 = 1826007639 bor 1131301421. +800645242 = 1826007639 bxor 1131301421. +168825889 = 791778547 band 177364009. +800316667 = 791778547 bor 177364009. +631490778 = 791778547 bxor 177364009. +-935165627 = -381252273 band -859074075. +-305160721 = -381252273 bor -859074075. +630004906 = -381252273 bxor -859074075. +-2046285983 = -1509380245 band -1901566111. +-1364660373 = -1509380245 bor -1901566111. +681625610 = -1509380245 bxor -1901566111. +1073745925 = 1652610887 band 1159927965. +1738792927 = 1652610887 bor 1159927965. +665047002 = 1652610887 bxor 1159927965. +630913 = 694788323 band 10330521. +704487931 = 694788323 bor 10330521. +703857018 = 694788323 bxor 10330521. +-930535403 = -326408129 band -878854571. +-274727297 = -326408129 bor -878854571. +655808106 = -326408129 bxor -878854571. +-2125969327 = -1478997669 band -1991709999. +-1344738341 = -1478997669 bor -1991709999. +781230986 = -1478997669 bxor -1991709999. +1241522181 = 1783111735 band 1335911181. +1877500735 = 1783111735 bor 1335911181. +635978554 = 1783111735 bxor 1335911181. +7602177 = 544508115 band 159195913. +696101851 = 544508115 bor 159195913. +688499674 = 544508115 bxor 159195913. +-868170235 = -319496401 band -867440955. +-318767121 = -319496401 bor -867440955. +549403114 = -319496401 bxor -867440955. +-2012730815 = -1434828981 band -1920390591. +-1342488757 = -1434828981 bor -1920390591. +670242058 = -1434828981 bxor -1920390591. +1135149349 = 1672185127 band 1140664701. +1677700479 = 1672185127 bor 1140664701. +542551130 = 1672185127 bxor 1140664701. +8470593 = 750865603 band 12050553. +754445563 = 750865603 bor 12050553. +745974970 = 750865603 bxor 12050553. +-893320683 = -354291169 band -875754699. +-336725185 = -354291169 bor -875754699. +556595498 = -354291169 bxor -875754699. +-2146434767 = -1522691781 band -2133842511. +-1510099525 = -1522691781 bor -2133842511. +636335242 = -1522691781 bxor -2133842511. +1124073989 = 1810499095 band 1192258541. +1878683647 = 1810499095 bor 1192258541. +754609658 = 1810499095 bxor 1192258541. +1362081 = 545189043 band 26532329. +570359291 = 545189043 bor 26532329. +568997210 = 545189043 bxor 26532329. +-1068490491 = -328097521 band -1026020443. +-285627473 = -328097521 bor -1026020443. +782863018 = -328097521 bxor -1026020443. +-2147476191 = -1590608085 band -2142970591. +-1586102485 = -1590608085 bor -2142970591. +561373706 = -1590608085 bxor -2142970591. +1073750533 = 1845666567 band 1097935453. +1869851487 = 1845666567 bor 1097935453. +796100954 = 1845666567 bxor 1097935453. +119015425 = 664561827 band 119213913. +664760315 = 664561827 bor 119213913. +545744890 = 664561827 bxor 119213913. +-981448683 = -310187009 band -974895083. +-303633409 = -310187009 bor -974895083. +677815274 = -310187009 bxor -974895083. +-2147205103 = -1457239781 band -2133962607. +-1443997285 = -1457239781 bor -2133962607. +703207818 = -1457239781 bxor -2133962607. +1110720709 = 1655987191 band 1333159117. +1878425599 = 1655987191 bor 1333159117. +767704890 = 1655987191 bxor 1333159117. +67141761 = 667467923 band 202473673. +802799835 = 667467923 bor 202473673. +735658074 = 667467923 bxor 202473673. +-987742075 = -273362193 band -987209595. +-272829713 = -273362193 bor -987209595. +714912362 = -273362193 bxor -987209595. +-1996390399 = -1448759541 band -1894547455. +-1346916597 = -1448759541 bor -1894547455. +649473802 = -1448759541 bxor -1894547455. +1077284901 = 1618882791 band 1094130493. +1635728383 = 1618882791 bor 1094130493. +558443482 = 1618882791 bxor 1094130493. +7480321 = 544404611 band 184495673. +721419963 = 544404611 bor 184495673. +713939642 = 544404611 bxor 184495673. +-939371307 = -362392097 band -862227211. +-285248001 = -362392097 bor -862227211. +654123306 = -362392097 bxor -862227211. +-2130681743 = -1593544453 band -1887736975. +-1350599685 = -1593544453 bor -1887736975. +780082058 = -1593544453 bxor -1887736975. +1250558341 = 1805590999 band 1250577837. +1805610495 = 1805590999 bor 1250577837. +555052154 = 1805590999 bxor 1250577837. +168428577 = 717882483 band 237705129. +787159035 = 717882483 bor 237705129. +618730458 = 717882483 bxor 237705129. +-1028389819 = -357141297 band -1007385243. +-336136721 = -357141297 bor -1007385243. +692253098 = -357141297 bxor -1007385243. +-1911749919 = -1353740565 band -1909648671. +-1351639317 = -1353740565 bor -1909648671. +560110602 = -1353740565 bxor -1909648671. +1107700741 = 1712729799 band 1124531229. +1729560287 = 1712729799 bor 1124531229. +621859546 = 1712729799 bxor 1124531229. +161230849 = 700248163 band 261897497. +800914811 = 700248163 bor 261897497. +639683962 = 700248163 bxor 261897497. +-1031798379 = -477876289 band -827682347. +-273760257 = -477876289 bor -827682347. +758038122 = -477876289 bxor -827682347. +-2046427055 = -1504311077 band -1894812079. +-1352696101 = -1504311077 bor -1894812079. +693730954 = -1504311077 bxor -1894812079. +1174406789 = 1872910263 band 1174677133. +1873180607 = 1872910263 bor 1174677133. +698773818 = 1872910263 bxor 1174677133. +152606721 = 704297043 band 152673929. +704364251 = 704297043 bor 152673929. +551757530 = 704297043 bxor 152673929. +-916159995 = -311523665 band -873162171. +-268525841 = -311523665 bor -873162171. +647634154 = -311523665 bxor -873162171. +-1988062015 = -1448681781 band -1916168767. +-1376788533 = -1448681781 bor -1916168767. +611273482 = -1448681781 bxor -1916168767. +1082166437 = 1707252903 band 1117310205. +1742396671 = 1707252903 bor 1117310205. +660230234 = 1707252903 bxor 1117310205. +2234433 = 569531459 band 69876729. +637173755 = 569531459 bor 69876729. +634939322 = 569531459 bxor 69876729. +-960489323 = -422282849 band -959865163. +-421658689 = -422282849 bor -959865163. +538830634 = -422282849 bxor -959865163. +-1937764303 = -1366224709 band -1916636879. +-1345097285 = -1366224709 bor -1916636879. +592667018 = -1366224709 bxor -1916636879. +1133636869 = 1672871319 band 1268510573. +1807745023 = 1672871319 bor 1268510573. +674108154 = 1672871319 bxor 1268510573. +1053729 = 567467059 band 169153897. +735567227 = 567467059 bor 169153897. +734513498 = 567467059 bxor 169153897. +-1044379643 = -472577905 band -975134939. +-403333201 = -472577905 bor -975134939. +641046442 = -472577905 bxor -975134939. +-2011101023 = -1406951765 band -1977546591. +-1373397333 = -1406951765 bor -1977546591. +637703690 = -1406951765 bxor -1977546591. +1109395589 = 1652259463 band 1201966557. +1744830431 = 1652259463 bor 1201966557. +635434842 = 1652259463 bxor 1201966557. +58796033 = 596326435 band 65088217. +602618619 = 596326435 bor 65088217. +543822586 = 596326435 bxor 65088217. +-905964779 = -296799361 band -877618283. +-268452865 = -296799361 bor -877618283. +637511914 = -296799361 bxor -877618283. +-2129917935 = -1423079269 band -2050204655. +-1343365989 = -1423079269 bor -2050204655. +786551946 = -1423079269 bxor -2050204655. +1073741893 = 1758598007 band 1091151949. +1776008063 = 1758598007 bor 1091151949. +702266170 = 1758598007 bxor 1091151949. +171995137 = 717910035 band 173374537. +719289435 = 717910035 bor 173374537. +547294298 = 717910035 bxor 173374537. +-1000304635 = -438175121 band -965700603. +-403571089 = -438175121 bor -965700603. +596733546 = -438175121 bxor -965700603. +-2111223167 = -1505898869 band -1955894399. +-1350570101 = -1505898869 bor -1955894399. +760653066 = -1505898869 bxor -1955894399. +1092618277 = 1798883431 band 1172455101. +1878720255 = 1798883431 bor 1172455101. +786101978 = 1798883431 bxor 1172455101. +83427329 = 620725251 band 100207033. +637504955 = 620725251 bor 100207033. +554077626 = 620725251 bxor 100207033. +-1073477547 = -269722273 band -1072199563. +-268444289 = -269722273 bor -1072199563. +805033258 = -269722273 bxor -1072199563. +-1994313615 = -1448906629 band -1922746639. +-1377339653 = -1448906629 bor -1922746639. +616973962 = -1448906629 bxor -1922746639. +1208226053 = 1810798935 band 1208308013. +1810880895 = 1810798935 bor 1208308013. +602654842 = 1810798935 bxor 1208308013. +152064801 = 693728243 band 252891945. +794555387 = 693728243 bor 252891945. +642490586 = 693728243 bxor 252891945. +-972269499 = -410166193 band -832800539. +-270697233 = -410166193 bor -832800539. +701572266 = -410166193 bxor -832800539. +-2124403103 = -1553109397 band -2048868767. +-1477575061 = -1553109397 bor -2048868767. +646828042 = -1553109397 bxor -2048868767. +1207993861 = 1794278983 band 1292492701. +1878777823 = 1794278983 bor 1292492701. +670783962 = 1794278983 bxor 1292492701. +142678145 = 684146659 band 229234841. +770703355 = 684146659 bor 229234841. +628025210 = 684146659 bxor 229234841. +-1063099115 = -308021441 band -1028233899. +-273156225 = -308021441 bor -1028233899. +789942890 = -308021441 bxor -1028233899. +-2109734831 = -1553282981 band -2033909295. +-1477457445 = -1553282981 bor -2033909295. +632277386 = -1553282981 bxor -2033909295. +1174571525 = 1711509303 band 1313270285. +1850208063 = 1711509303 bor 1313270285. +675636538 = 1711509303 bxor 1313270285. +159711745 = 771221459 band 159717897. +771227611 = 771221459 bor 159717897. +611515866 = 771221459 bxor 159717897. +-934540283 = -389075409 band -899920443. +-354455569 = -389075409 bor -899920443. +580084714 = -389075409 bxor -899920443. +-1993867199 = -1423278517 band -1984364223. +-1413775541 = -1423278517 bor -1984364223. +580091658 = -1423278517 bxor -1984364223. +1216360485 = 1755362343 band 1221816445. +1760818303 = 1755362343 bor 1221816445. +544457818 = 1755362343 bxor 1221816445. +134873921 = 760900547 band 170628985. +796655611 = 760900547 bor 170628985. +661781690 = 760900547 bxor 170628985. +-1002176491 = -445775585 band -834325963. +-277925057 = -445775585 bor -834325963. +724251434 = -445775585 bxor -834325963. +-2145152975 = -1376022469 band -2145141583. +-1376011077 = -1376022469 bor -2145141583. +769141898 = -1376022469 bxor -2145141583. +1275097093 = 1812526359 band 1300656877. +1838086143 = 1812526359 bor 1300656877. +562989050 = 1812526359 bxor 1300656877. +67387553 = 622709683 band 115626217. +670948347 = 622709683 bor 115626217. +603560794 = 622709683 bxor 115626217. +-1056436219 = -442535921 band -1020783963. +-406883665 = -442535921 bor -1020783963. +649552554 = -442535921 bxor -1020783963. +-2144586719 = -1595081173 band -2094255071. +-1544749525 = -1595081173 bor -2094255071. +599837194 = -1595081173 bxor -2094255071. +1077039109 = 1731940871 band 1089925469. +1744827231 = 1731940871 bor 1089925469. +667788122 = 1731940871 bxor 1089925469. +70256129 = 758187939 band 112608857. +800540667 = 758187939 bor 112608857. +730284538 = 758187939 bxor 112608857. +-1052612075 = -515736833 band -914624747. +-377749505 = -515736833 bor -914624747. +674862570 = -515736833 bxor -914624747. +-2104934383 = -1429354469 band -2085001327. +-1409421413 = -1429354469 bor -2085001327. +695512970 = -1429354469 bxor -2085001327. +1249036997 = 1861667575 band 1266412493. +1879043071 = 1861667575 bor 1266412493. +630006074 = 1861667575 bxor 1266412493. +4200321 = 658710419 band 6846409. +661356507 = 658710419 bor 6846409. +657156186 = 658710419 bxor 6846409. +-982122107 = -436854289 band -847788155. +-302520337 = -436854289 bor -847788155. +679601770 = -436854289 bxor -847788155. +-2145368575 = -1540559349 band -1972218111. +-1367408885 = -1540559349 bor -1972218111. +777959690 = -1540559349 bxor -1972218111. +1093157413 = 1706713063 band 1227645501. +1841201151 = 1706713063 bor 1227645501. +748043738 = 1706713063 bxor 1227645501. +176226561 = 784536451 band 176284985. +784594875 = 784536451 bor 176284985. +608368314 = 784536451 bxor 176284985. +-955252523 = -417766177 band -955081739. +-417595393 = -417766177 bor -955081739. +537657130 = -417766177 bxor -955081739. +-2028469647 = -1487310853 band -2017590671. +-1476431877 = -1487310853 bor -2017590671. +552037770 = -1487310853 bxor -2017590671. +1237651589 = 1808077015 band 1239372973. +1809798399 = 1808077015 bor 1239372973. +572146810 = 1808077015 bxor 1239372973. +139035169 = 685761395 band 189370025. +736096251 = 685761395 bor 189370025. +597061082 = 685761395 bxor 189370025. +-939311035 = -305445937 band -905745307. +-271880209 = -305445937 bor -905745307. +667430826 = -305445937 bxor -905745307. +-2143139359 = -1604170261 band -2084345375. +-1545376277 = -1604170261 bor -2084345375. +597763082 = -1604170261 bxor -2084345375. +1090633989 = 1863704007 band 1093387037. +1866457055 = 1863704007 bor 1093387037. +775823066 = 1863704007 bxor 1093387037. +8389633 = 612929379 band 147223577. +751763323 = 612929379 bor 147223577. +743373690 = 612929379 bxor 147223577. +-1061144427 = -387268929 band -977192747. +-303317249 = -387268929 bor -977192747. +757827178 = -387268929 bxor -977192747. +-1946122927 = -1391032357 band -1905685167. +-1350594597 = -1391032357 bor -1905685167. +595528330 = -1391032357 bxor -1905685167. +1114145925 = 1802225335 band 1181265293. +1869344703 = 1802225335 bor 1181265293. +755198778 = 1802225335 bxor 1181265293. +137106689 = 711726931 band 146773385. +721393627 = 711726931 bor 146773385. +584286938 = 711726931 bxor 146773385. +-989724411 = -317270609 band -981270203. +-308816401 = -317270609 bor -981270203. +680908010 = -317270609 bxor -981270203. +-1929048895 = -1392173621 band -1890095935. +-1353220661 = -1392173621 bor -1890095935. +575828234 = -1392173621 bxor -1890095935. +1074070437 = 1782959015 band 1152193533. +1861082111 = 1782959015 bor 1152193533. +787011674 = 1782959015 bxor 1152193533. +12153409 = 754547523 band 12317433. +754711547 = 754547523 bor 12317433. +742558138 = 754547523 bxor 12317433. +-1070694251 = -458323809 band -1069562443. +-457192001 = -458323809 bor -1069562443. +613502250 = -458323809 bxor -1069562443. +-2123102159 = -1585639493 band -2047604687. +-1510142021 = -1585639493 bor -2047604687. +612960138 = -1585639493 bxor -2047604687. +1120068613 = 1659038871 band 1255143021. +1794113279 = 1659038871 bor 1255143021. +674044666 = 1659038871 bxor 1255143021. +165921 = 677362483 band 100830313. +778026875 = 677362483 bor 100830313. +777860954 = 677362483 bxor 100830313. +-931101179 = -271526001 band -928086491. +-268511313 = -271526001 bor -928086491. +662589866 = -271526001 bxor -928086491. +-1996202591 = -1383244373 band -1989779551. +-1376821333 = -1383244373 bor -1989779551. +619381258 = -1383244373 bxor -1989779551. +1245708421 = 1782720903 band 1265128669. +1802141151 = 1782720903 bor 1265128669. +556432730 = 1782720903 bxor 1265128669. +8929537 = 579720995 band 228221401. +799012859 = 579720995 bor 228221401. +790083322 = 579720995 bxor 228221401. +-1002159595 = -463682945 band -851033451. +-312556801 = -463682945 bor -851033451. +689602794 = -463682945 bxor -851033451. +-2147155183 = -1509619813 band -2003471599. +-1365936229 = -1509619813 bor -2003471599. +781218954 = -1509619813 bxor -2003471599. +1073742405 = 1663206007 band 1288515405. +1877979007 = 1663206007 bor 1288515405. +804236602 = 1663206007 bxor 1288515405. +134365953 = 724750099 band 206205769. +796589915 = 724750099 bor 206205769. +662223962 = 724750099 bxor 206205769. +-936294139 = -302954129 band -935462139. +-302122129 = -302954129 bor -935462139. +634172010 = -302954129 bxor -935462139. +-2145386367 = -1586295413 band -1977073023. +-1417982069 = -1586295413 bor -1977073023. +727404298 = -1586295413 bxor -1977073023. +1207993637 = 1845688167 band 1226147261. +1863841791 = 1845688167 bor 1226147261. +655848154 = 1845688167 bxor 1226147261. +43614209 = 733848323 band 110739641. +800973755 = 733848323 bor 110739641. +757359546 = 733848323 bxor 110739641. +-846451627 = -303207329 band -812863627. +-269619329 = -303207329 bor -812863627. +576832298 = -303207329 bxor -812863627. +-2012983951 = -1473876101 band -1937388047. +-1398280197 = -1473876101 bor -1937388047. +614703754 = -1473876101 bxor -1937388047. +1207961605 = 1763870807 band 1310218285. +1866127487 = 1763870807 bor 1310218285. +658165882 = 1763870807 bxor 1310218285. +5063201 = 660427507 band 13584937. +668949243 = 660427507 bor 13584937. +663886042 = 660427507 bxor 13584937. +-1067447483 = -344970417 band -991338523. +-268861457 = -344970417 bor -991338523. +798586026 = -344970417 bxor -991338523. +-2080111263 = -1540477589 band -2049632927. +-1509999253 = -1540477589 bor -2049632927. +570112010 = -1540477589 bxor -2049632927. +1073751045 = 1619014983 band 1298966173. +1844230111 = 1619014983 bor 1298966173. +770479066 = 1619014983 bxor 1298966173. +167775873 = 721477347 band 250744729. +804446203 = 721477347 bor 250744729. +636670330 = 721477347 bxor 250744729. +-1052244971 = -480737729 band -976548779. +-405041537 = -480737729 bor -976548779. +647203434 = -480737729 bxor -976548779. +-2124873647 = -1587984549 band -2080565039. +-1543675941 = -1587984549 bor -2080565039. +581197706 = -1587984549 bxor -2080565039. +1279815685 = 1843068471 band 1281978637. +1845231423 = 1843068471 bor 1281978637. +565415738 = 1843068471 bxor 1281978637. +71368705 = 760694483 band 80285961. +769611739 = 760694483 bor 80285961. +698243034 = 760694483 bxor 80285961. +-935316475 = -398099153 band -882330427. +-345113105 = -398099153 bor -882330427. +590203370 = -398099153 bxor -882330427. +-1943758783 = -1388921525 band -1935353791. +-1380516533 = -1388921525 bor -1935353791. +563242250 = -1388921525 bxor -1935353791. +1075946277 = 1756488487 band 1143322493. +1823864703 = 1756488487 bor 1143322493. +747918426 = 1756488487 bxor 1143322493. +80415297 = 785353411 band 98258553. +803196667 = 785353411 bor 98258553. +722781370 = 785353411 bxor 98258553. +-1030746091 = -493481953 band -893822667. +-356558529 = -493481953 bor -893822667. +674187562 = -493481953 bxor -893822667. +-2062482639 = -1491759301 band -1926016079. +-1355292741 = -1491759301 bor -1926016079. +707189898 = -1491759301 bxor -1926016079. +1077960709 = 1715725335 band 1098414573. +1736179199 = 1715725335 bor 1098414573. +658218490 = 1715725335 bxor 1098414573. +17334945 = 697871027 band 91211753. +771747835 = 697871027 bor 91211753. +754412890 = 697871027 bxor 91211753. +-1067370235 = -529973489 band -999032411. +-461635665 = -529973489 bor -999032411. +605734570 = -529973489 bxor -999032411. +-2147186399 = -1610302165 band -1966109919. +-1429225685 = -1610302165 bor -1966109919. +717960714 = -1610302165 bxor -1966109919. +1083179013 = 1771045127 band 1157150813. +1845016927 = 1771045127 bor 1157150813. +761837914 = 1771045127 bxor 1157150813. +8463361 = 564242083 band 109935961. +665714683 = 564242083 bor 109935961. +657251322 = 564242083 bxor 109935961. +-988938219 = -442627585 band -988834283. +-442523649 = -442627585 bor -988834283. +546414570 = -442627585 bxor -988834283. +-2109716975 = -1428994277 band -2107605359. +-1426882661 = -1428994277 bor -2107605359. +682834314 = -1428994277 bxor -2107605359. +1112879301 = 1666529783 band 1123906253. +1677556735 = 1666529783 bor 1123906253. +564677434 = 1666529783 bxor 1123906253. +10055297 = 614039187 band 201027273. +805011163 = 614039187 bor 201027273. +794955866 = 614039187 bxor 201027273. +-1060953979 = -338464529 band -993841531. +-271352081 = -338464529 bor -993841531. +789601898 = -338464529 bxor -993841531. +-2013254655 = -1408226037 band -2004013567. +-1398984949 = -1408226037 bor -2004013567. +614269706 = -1408226037 bxor -2004013567. +1108379685 = 1645383399 band 1134405949. +1671409663 = 1645383399 bor 1134405949. +563029978 = 1645383399 bxor 1134405949. +138416129 = 703541891 band 138452025. +703577787 = 703541891 bor 138452025. +565161658 = 703541891 bxor 138452025. +-1040170283 = -496471073 band -947535115. +-403835905 = -496471073 bor -947535115. +636334378 = -496471073 bxor -947535115. +-2012739471 = -1442156805 band -1984128655. +-1413545989 = -1442156805 bor -1984128655. +599193482 = -1442156805 bxor -1984128655. +1107319685 = 1644625879 band 1118854061. +1656160255 = 1644625879 bor 1118854061. +548840570 = 1644625879 bxor 1118854061. +8388641 = 584172147 band 228853161. +804636667 = 584172147 bor 228853161. +796248026 = 584172147 bxor 228853161. +-871624123 = -293858609 band -854699163. +-276933649 = -293858609 bor -854699163. +594690474 = -293858609 bxor -854699163. +-2012151583 = -1395585813 band -1978285855. +-1361720085 = -1395585813 bor -1978285855. +650431498 = -1395585813 bxor -1978285855. +1291880453 = 1831963847 band 1338804765. +1878888159 = 1831963847 bor 1338804765. +587007706 = 1831963847 bxor 1338804765. +169880065 = 707800675 band 237808409. +775729019 = 707800675 bor 237808409. +605848954 = 707800675 bxor 237808409. +-1061073515 = -353546817 band -1059856427. +-352329729 = -353546817 bor -1059856427. +708743786 = -353546817 bxor -1059856427. +-2077031343 = -1372387621 band -2055232431. +-1350588709 = -1372387621 bor -2055232431. +726442634 = -1372387621 bxor -2055232431. +1245787269 = 1800484279 band 1313420429. +1868117439 = 1800484279 bor 1313420429. +622330170 = 1800484279 bxor 1313420429. +10552321 = 616134227 band 195136649. +800718555 = 616134227 bor 195136649. +790166234 = 616134227 bxor 195136649. +-938926075 = -396680017 band -905091003. +-362844945 = -396680017 bor -905091003. +576081130 = -396680017 bxor -905091003. +-1985920831 = -1447076661 band -1885256767. +-1346412597 = -1447076661 bor -1885256767. +639508234 = -1447076661 bxor -1885256767. +1092901541 = 1642396327 band 1161648893. +1711143679 = 1642396327 bor 1161648893. +618242138 = 1642396327 bxor 1161648893. +8947777 = 551328323 band 126462457. +668843003 = 551328323 bor 126462457. +659895226 = 551328323 bxor 126462457. +-920615787 = -316368993 band -877531979. +-273285185 = -316368993 bor -877531979. +647330602 = -316368993 bxor -877531979. +-2134831567 = -1396371781 band -2082365647. +-1343905861 = -1396371781 bor -2082365647. +790925706 = -1396371781 bxor -2082365647. +1143724293 = 1680595863 band 1333788013. +1870659583 = 1680595863 bor 1333788013. +726935290 = 1680595863 bxor 1333788013. +34079265 = 650680883 band 53216105. +669817723 = 650680883 bor 53216105. +635738458 = 650680883 bxor 53216105. +-999807995 = -446126449 band -998740699. +-445059153 = -446126449 bor -998740699. +554748842 = -446126449 bxor -998740699. +-2075978591 = -1504502613 band -2056800607. +-1485324629 = -1504502613 bor -2056800607. +590653962 = -1504502613 bxor -2056800607. +1126176901 = 1663359111 band 1269308381. +1806490591 = 1663359111 bor 1269308381. +680313690 = 1663359111 bxor 1269308381. +135008257 = 678196771 band 261069017. +804257531 = 678196771 bor 261069017. +669249274 = 678196771 bxor 261069017. +-1039777515 = -486125185 band -824710763. +-271058433 = -486125185 bor -824710763. +768719082 = -486125185 bxor -824710763. +-2028436975 = -1489467749 band -1894086127. +-1355116901 = -1489467749 bor -1894086127. +673320074 = -1489467749 bxor -1894086127. +1275899973 = 1838084471 band 1275901517. +1838086015 = 1838084471 bor 1275901517. +562186042 = 1838084471 bxor 1275901517. +24324609 = 561458707 band 226191945. +763326043 = 561458707 bor 226191945. +739001434 = 561458707 bxor 226191945. +-1056702459 = -308504465 band -1056480763. +-308282769 = -308504465 bor -1056480763. +748419690 = -308504465 bxor -1056480763. +-2113927039 = -1576776565 band -2086594175. +-1549443701 = -1576776565 bor -2086594175. +564483338 = -1576776565 bxor -2086594175. +1186989093 = 1877550695 band 1187302589. +1877864191 = 1877550695 bor 1187302589. +690875098 = 1877550695 bxor 1187302589. +89539073 = 660062723 band 225867705. +796391355 = 660062723 bor 225867705. +706852282 = 660062723 bxor 225867705. +-1064807851 = -494240929 band -855779723. +-285212801 = -494240929 bor -855779723. +779595050 = -494240929 bxor -855779723. +-1996462991 = -1425707397 band -1922931471. +-1352175877 = -1425707397 bor -1922931471. +644287114 = -1425707397 bxor -1922931471. +1143101189 = 1685223255 band 1168596781. +1710718847 = 1685223255 bor 1168596781. +567617658 = 1685223255 bxor 1168596781. +151322913 = 691876339 band 264749353. +805302779 = 691876339 bor 264749353. +653979866 = 691876339 bxor 264749353. +-1067302331 = -454100401 band -1066252571. +-453050641 = -454100401 bor -1066252571. +614251690 = -454100401 bxor -1066252571. +-2013238175 = -1471484821 band -1903858591. +-1362105237 = -1471484821 bor -1903858591. +651132938 = -1471484821 bxor -1903858591. +1107911685 = 1663689799 band 1179348381. +1735126495 = 1663689799 bor 1179348381. +627214810 = 1663689799 bxor 1179348381. +1459329 = 538344931 band 74860185. +611745787 = 538344931 bor 74860185. +610286458 = 538344931 bxor 74860185. +-997650155 = -307686081 band -992234667. +-302270593 = -307686081 bor -992234667. +695379562 = -307686081 bxor -992234667. +-2136930735 = -1583102373 band -2131677231. +-1577848869 = -1583102373 bor -2131677231. +559081866 = -1583102373 bxor -2131677231. +1074161669 = 1640918327 band 1242036237. +1808792895 = 1640918327 bor 1242036237. +734631226 = 1640918327 bxor 1242036237. +167772161 = 781362643 band 189335561. +802926043 = 781362643 bor 189335561. +635153882 = 781362643 bxor 189335561. +-883881979 = -346567633 band -814670907. +-277356561 = -346567633 bor -814670907. +606525418 = -346567633 bxor -814670907. +-2146653119 = -1600193461 band -2041794751. +-1495335093 = -1600193461 bor -2041794751. +651318026 = -1600193461 bxor -2041794751. +1104351781 = 1675563559 band 1173618301. +1744830079 = 1675563559 bor 1173618301. +640478298 = 1675563559 bxor 1173618301. +16777537 = 555788739 band 63374713. +602385915 = 555788739 bor 63374713. +585608378 = 555788739 bxor 63374713. +-1073217515 = -497410273 band -1054244811. +-478437569 = -497410273 bor -1054244811. +594779946 = -497410273 bxor -1054244811. +-2138404303 = -1601466821 band -2013336911. +-1476399429 = -1601466821 bor -2013336911. +662004874 = -1601466821 bxor -2013336911. +1115848709 = 1788531479 band 1122402541. +1795085311 = 1788531479 bor 1122402541. +679236602 = 1788531479 bxor 1122402541. +220661921 = 770673075 band 221724393. +771735547 = 770673075 bor 221724393. +551073626 = 770673075 bxor 221724393. +-997523451 = -321974769 band -960765787. +-285217105 = -321974769 bor -960765787. +712306346 = -321974769 bxor -960765787. +-2044174303 = -1367835605 band -2026970591. +-1350631893 = -1367835605 bor -2026970591. +693542410 = -1367835605 bxor -2026970591. +1157640197 = 1694543879 band 1299611485. +1836515167 = 1694543879 bor 1299611485. +678874970 = 1694543879 bxor 1299611485. +77595649 = 619595171 band 111195225. +653194747 = 619595171 bor 111195225. +575599098 = 619595171 bxor 111195225. +-929753067 = -359294721 band -929088235. +-358629889 = -359294721 bor -929088235. +571123178 = -359294721 bxor -929088235. +-2013232111 = -1456159205 band -1933339247. +-1376266341 = -1456159205 bor -1933339247. +636965770 = -1456159205 bxor -1933339247. +1170909381 = 1875880183 band 1174075853. +1879046655 = 1875880183 bor 1174075853. +708137274 = 1875880183 bxor 1174075853. +248137089 = 801889683 band 248145353. +801897947 = 801889683 bor 248145353. +553760858 = 801889683 bxor 248145353. +-1056402043 = -515063825 band -888498811. +-347160593 = -515063825 bor -888498811. +709241450 = -515063825 bxor -888498811. +-2126248959 = -1588630517 band -1989933823. +-1452315381 = -1588630517 bor -1989933823. +673933578 = -1588630517 bxor -1989933823. +1082306597 = 1703329255 band 1082847293. +1703869951 = 1703329255 bor 1082847293. +621563354 = 1703329255 bxor 1082847293. +3363073 = 569856387 band 70996793. +637490107 = 569856387 bor 70996793. +634127034 = 569856387 bxor 70996793. +-867139371 = -330071329 band -839587339. +-302519297 = -330071329 bor -839587339. +564620074 = -330071329 bxor -839587339. +-2129190799 = -1458082309 band -2055786383. +-1384677893 = -1458082309 bor -2055786383. +744512906 = -1458082309 bxor -2055786383. +1147429509 = 1852108503 band 1157456557. +1862135551 = 1852108503 bor 1157456557. +714706042 = 1852108503 bxor 1157456557. +1712161 = 681550195 band 87719081. +767557115 = 681550195 bor 87719081. +765844954 = 681550195 bxor 87719081. +-872406971 = -322379313 band -854246811. +-304219153 = -322379313 bor -854246811. +568187818 = -322379313 bxor -854246811. +-2147482655 = -1533293589 band -2128341023. +-1514151957 = -1533293589 bor -2128341023. +633330698 = -1533293589 bxor -2128341023. +1080627461 = 1617509319 band 1323913501. +1860795359 = 1617509319 bor 1323913501. +780167898 = 1617509319 bxor 1323913501. +176340993 = 716426595 band 265216537. +805302139 = 716426595 bor 265216537. +628961146 = 716426595 bxor 265216537. +-914193259 = -376709953 band -807237931. +-269754625 = -376709953 bor -807237931. +644438634 = -376709953 bxor -807237931. +-2147385007 = -1448376869 band -2075018415. +-1376010277 = -1448376869 bor -2075018415. +771374730 = -1448376869 bxor -2075018415. +1291886725 = 1867687095 band 1302707085. +1878507455 = 1867687095 bor 1302707085. +586620730 = 1867687095 bxor 1302707085. +10649857 = 685954387 band 29328265. +704632795 = 685954387 bor 29328265. +693982938 = 685954387 bxor 29328265. +-921484539 = -281316433 band -913060027. +-272891921 = -281316433 bor -913060027. +648592618 = -281316433 bxor -913060027. +-1903879487 = -1344955445 band -1901651263. +-1342727221 = -1344955445 bor -1901651263. +561152266 = -1344955445 bxor -1901651263. +1140859301 = 1822435751 band 1145676285. +1827252735 = 1822435751 bor 1145676285. +686393434 = 1822435751 bxor 1145676285. +143859777 = 765180227 band 143876345. +765196795 = 765180227 bor 143876345. +621337018 = 765180227 bxor 143876345. +-1071644011 = -533289313 band -920644683. +-382289985 = -533289313 bor -920644683. +689354026 = -533289313 bxor -920644683. +-2146892751 = -1603727941 band -2020919759. +-1477754949 = -1603727941 bor -2020919759. +669137802 = -1603727941 bxor -2020919759. +1098907653 = 1737542295 band 1236010093. +1874644735 = 1737542295 bor 1236010093. +775737082 = 1737542295 bxor 1236010093. +16873505 = 755857715 band 26311273. +765295483 = 755857715 bor 26311273. +748421978 = 755857715 bxor 26311273. +-1071885307 = -459508337 band -918662107. +-306285137 = -459508337 bor -918662107. +765600170 = -459508337 bxor -918662107. +-2044458591 = -1502291029 band -1910174303. +-1368006741 = -1502291029 bor -1910174303. +676451850 = -1502291029 bxor -1910174303. +1210286725 = 1831044999 band 1214505693. +1835263967 = 1831044999 bor 1214505693. +624977242 = 1831044999 bxor 1214505693. +16778497 = 623318307 band 163631065. +770170875 = 623318307 bor 163631065. +753392378 = 623318307 bxor 163631065. +-1069449195 = -364126081 band -1067085675. +-361762561 = -364126081 bor -1067085675. +707686634 = -364126081 bxor -1067085675. +-2008547055 = -1362623077 band -1990483695. +-1344559717 = -1362623077 bor -1990483695. +663987338 = -1362623077 bxor -1990483695. +1207967813 = 1746362487 band 1321745741. +1860140415 = 1746362487 bor 1321745741. +652172602 = 1746362487 bxor 1321745741. +226492673 = 764906771 band 233333065. +771747163 = 764906771 bor 233333065. +545254490 = 764906771 bxor 233333065. +-1061109499 = -454826129 band -1060321019. +-454037649 = -454826129 bor -1060321019. +607071850 = -454826129 bxor -1060321019. +-2016313215 = -1477342325 band -2016022399. +-1477051509 = -1477342325 bor -2016022399. +539261706 = -1477342325 bxor -2016022399. +1088426277 = 1626035559 band 1324356541. +1861965823 = 1626035559 bor 1324356541. +773539546 = 1626035559 bxor 1324356541. +42803201 = 667803907 band 177155769. +802156475 = 667803907 bor 177155769. +759353274 = 667803907 bxor 177155769. +-935163819 = -305952161 band -932512395. +-303300737 = -305952161 bor -932512395. +631863082 = -305952161 bxor -932512395. +-2109707919 = -1572835973 band -1879376911. +-1342504965 = -1572835973 bor -1879376911. +767202954 = -1572835973 bxor -1879376911. +1284662789 = 1843291735 band 1320314413. +1878943359 = 1843291735 bor 1320314413. +594280570 = 1843291735 bxor 1320314413. +184029217 = 788074739 band 201078825. +805124347 = 788074739 bor 201078825. +621095130 = 788074739 bxor 201078825. +-1073673915 = -469120689 band -1057542683. +-452989457 = -469120689 bor -1057542683. +620684458 = -469120689 bxor -1057542683. +-1883143327 = -1346131093 band -1879981215. +-1342968981 = -1346131093 bor -1879981215. +540174346 = -1346131093 bxor -1879981215. +1118179333 = 1659867975 band 1202074781. +1743763423 = 1659867975 bor 1202074781. +625584090 = 1659867975 bxor 1202074781. +134225025 = 671620323 band 238452121. +775847419 = 671620323 bor 238452121. +641622394 = 671620323 bxor 238452121. +-864026603 = -325737409 band -806856107. +-268566913 = -325737409 bor -806856107. +595459690 = -325737409 bxor -806856107. +-2080357295 = -1538636453 band -1918810415. +-1377089573 = -1538636453 bor -1918810415. +703267722 = -1538636453 bxor -1918810415. +1090542597 = 1641929783 band 1193443085. +1744830271 = 1641929783 bor 1193443085. +654287674 = 1641929783 bxor 1193443085. +16778241 = 564790483 band 218431241. +766443483 = 564790483 bor 218431241. +749665242 = 564790483 bxor 218431241. +-1039924731 = -502916305 band -965377339. +-428368913 = -502916305 bor -965377339. +611555818 = -502916305 bxor -965377339. +-2078277055 = -1520223413 band -2035251647. +-1477198005 = -1520223413 bor -2035251647. +601079050 = -1520223413 bxor -2035251647. +1244152101 = 1781023015 band 1312703869. +1849574783 = 1781023015 bor 1312703869. +605422682 = 1781023015 bxor 1312703869. +5015617 = 609077443 band 65977465. +670039291 = 609077443 bor 65977465. +665023674 = 609077443 bxor 65977465. +-1064294891 = -457560545 band -1047156939. +-440422593 = -457560545 bor -1047156939. +623872298 = -457560545 bxor -1047156939. +-2147188431 = -1436709573 band -2138668623. +-1428189765 = -1436709573 bor -2138668623. +718998666 = -1436709573 bxor -2138668623. +1090552325 = 1762509335 band 1104185325. +1776142335 = 1762509335 bor 1104185325. +685590010 = 1762509335 bxor 1104185325. +35791009 = 572680371 band 238728681. +775618043 = 572680371 bor 238728681. +739827034 = 572680371 bxor 238728681. +-925842171 = -355410673 band -905984091. +-335552593 = -355410673 bor -905984091. +590289578 = -355410673 bxor -905984091. +-2008532703 = -1404552405 band -2008401631. +-1404421333 = -1404552405 bor -2008401631. +604111370 = -1404552405 bxor -2008401631. +1207977477 = 1770872583 band 1248872029. +1811767135 = 1770872583 bor 1248872029. +603789658 = 1770872583 bxor 1248872029. +101113857 = 655811747 band 116386649. +671084539 = 655811747 bor 116386649. +569970682 = 655811747 bxor 116386649. +-1071111147 = -534173697 band -1003822059. +-466884609 = -534173697 bor -1003822059. +604226538 = -534173697 bxor -1003822059. +-2132671471 = -1510849253 band -2099073903. +-1477251685 = -1510849253 bor -2099073903. +655419786 = -1510849253 bxor -2099073903. +1147404485 = 1684412407 band 1148485837. +1685493759 = 1684412407 bor 1148485837. +538089274 = 1684412407 bxor 1148485837. +147856513 = 685390995 band 148200649. +685735131 = 685390995 bor 148200649. +537878618 = 685390995 bxor 148200649. +-1069544315 = -429781265 band -1068630907. +-428867857 = -429781265 bor -1068630907. +640676458 = -429781265 bxor -1068630907. +-2132637695 = -1544901877 band -1929978879. +-1342243061 = -1544901877 bor -1929978879. +790394634 = -1544901877 bxor -1929978879. +1075061797 = 1612115175 band 1341404989. +1878458367 = 1612115175 bor 1341404989. +803396570 = 1612115175 bxor 1341404989. +106037249 = 651915395 band 242354745. +788232891 = 651915395 bor 242354745. +682195642 = 651915395 bxor 242354745. +-1069543211 = -455437857 band -899673867. +-285568513 = -455437857 bor -899673867. +783974698 = -455437857 bxor -899673867. +-2139077519 = -1535087365 band -1964128399. +-1360138245 = -1535087365 bor -1964128399. +778939274 = -1535087365 bxor -1964128399. +1086736773 = 1625218519 band 1086745005. +1625226751 = 1625218519 bor 1086745005. +538489978 = 1625218519 bxor 1086745005. +34111521 = 709460083 band 34403241. +709751803 = 709460083 bor 34403241. +675640282 = 709460083 bxor 34403241. +-938467259 = -391008049 band -904388251. +-356929041 = -391008049 bor -904388251. +581538218 = -391008049 bxor -904388251. +-2134766879 = -1480422677 band -1997639967. +-1343295765 = -1480422677 bor -1997639967. +791471114 = -1480422677 bxor -1997639967. +1216350213 = 1757211335 band 1317148701. +1858009823 = 1757211335 bor 1317148701. +641659610 = 1757211335 bxor 1317148701. +67176449 = 638807139 band 229447961. +801078651 = 638807139 bor 229447961. +733902202 = 638807139 bxor 229447961. +-1060886123 = -456758337 band -1024643627. +-420515841 = -456758337 bor -1024643627. +640370282 = -456758337 bxor -1024643627. +-1971322799 = -1350564645 band -1965043119. +-1344284965 = -1350564645 bor -1965043119. +627037834 = -1350564645 bxor -1965043119. +1148191365 = 1735398327 band 1149125261. +1736332223 = 1735398327 bor 1149125261. +588140858 = 1735398327 bxor 1149125261. +34091009 = 652751955 band 186219145. +804880091 = 652751955 bor 186219145. +770789082 = 652751955 bxor 186219145. +-1072299515 = -508050769 band -1005177275. +-440928529 = -508050769 bor -1005177275. +631370986 = -508050769 bxor -1005177275. +-1941909311 = -1354245429 band -1939279423. +-1351615541 = -1354245429 bor -1939279423. +590293770 = -1354245429 bxor -1939279423. +1079068837 = 1786206375 band 1104275709. +1811413247 = 1786206375 bor 1104275709. +732344410 = 1786206375 bxor 1104275709. +51384385 = 590796867 band 64559097. +603971579 = 590796867 bor 64559097. +552587194 = 590796867 bxor 64559097. +-931123051 = -303778401 band -930465099. +-303120449 = -303778401 bor -930465099. +628002602 = -303778401 bxor -930465099. +-2141189071 = -1402401605 band -2131702479. +-1392915013 = -1402401605 bor -2131702479. +748274058 = -1402401605 bxor -2131702479. +1225787653 = 1829878167 band 1230244717. +1834335231 = 1829878167 bor 1230244717. +608547578 = 1829878167 bxor 1230244717. +19025953 = 724457523 band 20115817. +725547387 = 724457523 bor 20115817. +706521434 = 724457523 bxor 20115817. +-989855739 = -311671665 band -956286171. +-278102097 = -311671665 bor -956286171. +711753642 = -311671665 bxor -956286171. +-2121138015 = -1376609621 band -2086771551. +-1342243157 = -1376609621 bor -2086771551. +778894858 = -1376609621 bxor -2086771551. +1075454085 = 1748907655 band 1100720605. +1774174175 = 1748907655 bor 1100720605. +698720090 = 1748907655 bxor 1100720605. +137102337 = 683521059 band 204343001. +750761723 = 683521059 bor 204343001. +613659386 = 683521059 bxor 204343001. +-1070782699 = -366121089 band -1041287275. +-336625665 = -366121089 bor -1041287275. +734157034 = -366121089 bxor -1041287275. +-2079293423 = -1397521253 band -2024228847. +-1342456677 = -1397521253 bor -2024228847. +736836746 = -1397521253 bxor -2024228847. +1086047301 = 1656475511 band 1157612621. +1728040831 = 1656475511 bor 1157612621. +641993530 = 1656475511 bxor 1157612621. +227624961 = 798223379 band 227629129. +798227547 = 798223379 bor 227629129. +570602586 = 798223379 bxor 227629129. +-1014616059 = -473483665 band -946982907. +-405850513 = -473483665 bor -946982907. +608765546 = -473483665 bxor -946982907. +-2113748351 = -1556428149 band -2033793151. +-1476472949 = -1556428149 bor -2033793151. +637275402 = -1556428149 bxor -2033793151. +1090584613 = 1628013671 band 1100438205. +1637867263 = 1628013671 bor 1100438205. +547282650 = 1628013671 bxor 1100438205. +220200961 = 757071875 band 233039289. +769910203 = 757071875 bor 233039289. +549709242 = 757071875 bxor 233039289. +-1047527339 = -275211937 band -1043061643. +-270746241 = -275211937 bor -1043061643. +776781098 = -275211937 bxor -1043061643. +-2075721615 = -1378390917 band -2075159823. +-1377829125 = -1378390917 bor -2075159823. +697892490 = -1378390917 bxor -2075159823. +1092633861 = 1701205335 band 1228500269. +1837071743 = 1701205335 bor 1228500269. +744437882 = 1701205335 bxor 1228500269. +44833 = 680587251 band 91008809. +771551227 = 680587251 bor 91008809. +771506394 = 680587251 bxor 91008809. +-1069543355 = -390031281 band -965208859. +-285696785 = -390031281 bor -965208859. +783846570 = -390031281 bxor -965208859. +-1978135967 = -1432851861 band -1978000799. +-1432716693 = -1432851861 bor -1978000799. +545419274 = -1432851861 bxor -1978000799. +1095778821 = 1875984967 band 1098709917. +1878916063 = 1875984967 bor 1098709917. +783137242 = 1875984967 bxor 1098709917. +1093761 = 584432611 band 204649625. +787988475 = 584432611 bor 204649625. +786894714 = 584432611 bxor 204649625. +-1072692971 = -534891713 band -957284011. +-419482753 = -534891713 bor -957284011. +653210218 = -534891713 bxor -957284011. +-2012461999 = -1454586789 band -1978835503. +-1420960293 = -1454586789 bor -1978835503. +591501706 = -1454586789 bxor -1978835503. +1107886597 = 1846102839 band 1136199181. +1874415423 = 1846102839 bor 1136199181. +766528826 = 1846102839 bxor 1136199181. +10248705 = 647848915 band 167573001. +805173211 = 647848915 bor 167573001. +794924506 = 647848915 bxor 167573001. +-1068472315 = -330274257 band -1066014267. +-327816209 = -330274257 bor -1066014267. +740656106 = -330274257 bxor -1066014267. +-1988077503 = -1417446837 band -1915724479. +-1345093813 = -1417446837 bor -1915724479. +642983690 = -1417446837 bxor -1915724479. +1224998949 = 1804431399 band 1292143741. +1871576191 = 1804431399 bor 1292143741. +646577242 = 1804431399 bxor 1292143741. +5399361 = 676784067 band 106066809. +777451515 = 676784067 bor 106066809. +772052154 = 676784067 bxor 106066809. +-910947307 = -373932769 band -872559051. +-335544513 = -373932769 bor -872559051. +575402794 = -373932769 bxor -872559051. +-2071328719 = -1534358469 band -2033575759. +-1496605509 = -1534358469 bor -2033575759. +574723210 = -1534358469 bxor -2033575759. +1075085317 = 1637658903 band 1312198381. +1874771967 = 1637658903 bor 1312198381. +799686650 = 1637658903 bxor 1312198381. +3146913 = 640763827 band 142224617. +779841531 = 640763827 bor 142224617. +776694618 = 640763827 bxor 142224617. +-902910971 = -361845745 band -834687323. +-293622097 = -361845745 bor -834687323. +609288874 = -361845745 bxor -834687323. +-2011066335 = -1452017109 band -1910403039. +-1351353813 = -1452017109 bor -1910403039. +659712522 = -1452017109 bxor -1910403039. +1126566917 = 1731595783 band 1273367901. +1878396767 = 1731595783 bor 1273367901. +751829850 = 1731595783 bxor 1273367901. +1769985 = 672891811 band 125510233. +796632059 = 672891811 bor 125510233. +794862074 = 672891811 bxor 125510233. +-971996651 = -430393601 band -944600299. +-402997249 = -430393601 bor -944600299. +568999402 = -430393601 bxor -944600299. +-2146844655 = -1593064421 band -2067938415. +-1514158181 = -1593064421 bor -2067938415. +632686474 = -1593064421 bxor -2067938415. +1074267845 = 1628997367 band 1315571661. +1870301183 = 1628997367 bor 1315571661. +796033338 = 1628997367 bxor 1315571661. +168039297 = 801414035 band 169628617. +803003355 = 801414035 bor 169628617. +634964058 = 801414035 bxor 169628617. +-1073659515 = -351052305 band -997366907. +-274759697 = -351052305 bor -997366907. +798899818 = -351052305 bxor -997366907. +-2092850687 = -1545475573 band -2092584191. +-1545209077 = -1545475573 bor -2092584191. +547641610 = -1545475573 bxor -2092584191. +1103174181 = 1640176615 band 1104772669. +1641775103 = 1640176615 bor 1104772669. +538600922 = 1640176615 bxor 1104772669. +8421633 = 681283459 band 115654969. +788516795 = 681283459 bor 115654969. +780095162 = 681283459 bxor 115654969. +-926605099 = -335699745 band -859359243. +-268453889 = -335699745 bor -859359243. +658151210 = -335699745 bxor -859359243. +-2013246863 = -1404736517 band -1977590159. +-1369079813 = -1404736517 bor -1977590159. +644167050 = -1404736517 bxor -1977590159. +1073758341 = 1769262295 band 1175154861. +1870658815 = 1769262295 bor 1175154861. +796900474 = 1769262295 bxor 1175154861. +67848737 = 667901811 band 68905641. +668958715 = 667901811 bor 68905641. +601109978 = 667901811 bxor 68905641. +-1072297915 = -499744817 band -1005123483. +-432570385 = -499744817 bor -1005123483. +639727530 = -499744817 bxor -1005123483. +-2143010335 = -1505408533 band -2123053599. +-1485451797 = -1505408533 bor -2123053599. +657558538 = -1505408533 bxor -2123053599. +1174706437 = 1714198983 band 1318510365. +1858002911 = 1714198983 bor 1318510365. +683296474 = 1714198983 bxor 1318510365. +71761921 = 743377763 band 130502681. +802118523 = 743377763 bor 130502681. +730356602 = 743377763 bxor 130502681. +-930033515 = -325256513 band -906767147. +-301990145 = -325256513 bor -906767147. +628043370 = -325256513 bxor -906767147. +-1994358447 = -1347386405 band -1993741999. +-1346769957 = -1347386405 bor -1993741999. +647588490 = -1347386405 bxor -1993741999. +1115717765 = 1672053431 band 1121110413. +1677446079 = 1672053431 bor 1121110413. +561728314 = 1672053431 bxor 1121110413. +109646081 = 784962387 band 128938377. +804254683 = 784962387 bor 128938377. +694608602 = 784962387 bxor 128938377. +-913305339 = -271576657 band -913007291. +-271278609 = -271576657 bor -913007291. +642026730 = -271576657 bxor -913007291. +-2012870463 = -1474946613 band -1998141247. +-1460217397 = -1474946613 bor -1998141247. +552653066 = -1474946613 bxor -1998141247. +1229064101 = 1802143655 band 1305882621. +1878962175 = 1802143655 bor 1305882621. +649898074 = 1802143655 bxor 1305882621. +17352257 = 565049155 band 156946169. +704643067 = 565049155 bor 156946169. +687290810 = 565049155 bxor 156946169. +-1071628139 = -433142625 band -906993227. +-268507713 = -433142625 bor -906993227. +803120426 = -433142625 bxor -906993227. +-2147483599 = -1597699141 band -2146278351. +-1596493893 = -1597699141 bor -2146278351. +550989706 = -1597699141 bxor -2146278351. +1143472133 = 1689168023 band 1316491885. +1862187775 = 1689168023 bor 1316491885. +718715642 = 1689168023 bxor 1316491885. +8225 = 556480307 band 34629737. +591101819 = 556480307 bor 34629737. +591093594 = 556480307 bxor 34629737. +-845676027 = -271051889 band -843177435. +-268553297 = -271051889 bor -843177435. +577122730 = -271051889 bxor -843177435. +-2067785311 = -1395893845 band -2049721439. +-1377829973 = -1395893845 bor -2049721439. +689955338 = -1395893845 bxor -2049721439. +1145331845 = 1685382535 band 1196388573. +1736439263 = 1685382535 bor 1196388573. +591107418 = 1685382535 bxor 1196388573. +34607361 = 590369571 band 114769369. +670531579 = 590369571 bor 114769369. +635924218 = 590369571 bxor 114769369. +-1038033387 = -492110209 band -1015751019. +-469827841 = -492110209 bor -1015751019. +568205546 = -492110209 bxor -1015751019. +-2146368751 = -1594162277 band -1995321583. +-1443115109 = -1594162277 bor -1995321583. +703253642 = -1594162277 bxor -1995321583. +1278216773 = 1836858999 band 1320373069. +1879015295 = 1836858999 bor 1320373069. +600798522 = 1836858999 bxor 1320373069. +73681665 = 661408531 band 209080137. +796807003 = 661408531 bor 209080137. +723125338 = 661408531 bxor 209080137. +-1069382395 = -364477073 band -984901883. +-279996561 = -364477073 bor -984901883. +789385834 = -364477073 bxor -984901883. +-2141190015 = -1545598581 band -2139906431. +-1544314997 = -1545598581 bor -2139906431. +596875018 = -1545598581 bxor -2139906431. +1073914149 = 1615049575 band 1320853949. +1861989375 = 1615049575 bor 1320853949. +788075226 = 1615049575 bxor 1320853949. +121904129 = 659431171 band 125082809. +662609851 = 659431171 bor 125082809. +540705722 = 659431171 bxor 125082809. +-938932139 = -402020257 band -918992011. +-382080129 = -402020257 bor -918992011. +556852010 = -402020257 bxor -918992011. +-2009061007 = -1379243141 band -1973409295. +-1343591429 = -1379243141 bor -1973409295. +665469578 = -1379243141 bxor -1973409295. +1091060741 = 1795834967 band 1161589805. +1866364031 = 1795834967 bor 1161589805. +775303290 = 1795834967 bxor 1161589805. +67110433 = 637849331 band 202974761. +773713659 = 637849331 bor 202974761. +706603226 = 637849331 bxor 202974761. +-1072667835 = -485267633 band -1057686555. +-470286353 = -485267633 bor -1057686555. +602381482 = -485267633 bxor -1057686555. +-2000150175 = -1463211669 band -1929481887. +-1392543381 = -1463211669 bor -1929481887. +607606794 = -1463211669 bxor -1929481887. +1104068613 = 1775169863 band 1137689245. +1808790495 = 1775169863 bor 1137689245. +704721882 = 1775169863 bxor 1137689245. +6965889 = 545217251 band 241888153. +780139515 = 545217251 bor 241888153. +773173626 = 545217251 bxor 241888153. +-935297003 = -398278081 band -906647467. +-369628545 = -398278081 bor -906647467. +565668458 = -398278081 bxor -906647467. +-2145304495 = -1599388837 band -2043317039. +-1497401381 = -1599388837 bor -2043317039. +647903114 = -1599388837 bxor -2043317039. +1178634245 = 1716566583 band 1338739981. +1876672319 = 1716566583 bor 1338739981. +698038074 = 1716566583 bxor 1338739981. +2146305 = 762102483 band 36760841. +796717019 = 762102483 bor 36760841. +794570714 = 762102483 bxor 36760841. +-936243195 = -365512401 band -848146235. +-277415441 = -365512401 bor -848146235. +658827754 = -365512401 bxor -848146235. +-2102644671 = -1560299189 band -1951648703. +-1409303221 = -1560299189 bor -1951648703. +693341450 = -1560299189 bxor -1951648703. +1074172709 = 1745788711 band 1111937917. +1783553919 = 1745788711 bor 1111937917. +709381210 = 1745788711 bxor 1111937917. +137364033 = 758908611 band 183642745. +805187323 = 758908611 bor 183642745. +667823290 = 758908611 bxor 183642745. +-1069530091 = -514962401 band -1067322059. +-512754369 = -514962401 bor -1067322059. +556775722 = -514962401 bxor -1067322059. +-1979610319 = -1357542597 band -1966493775. +-1344426053 = -1357542597 bor -1966493775. +635184266 = -1357542597 bxor -1966493775. +1073774597 = 1682415639 band 1209570797. +1818211839 = 1682415639 bor 1209570797. +744437242 = 1682415639 bxor 1209570797. +169091745 = 706487987 band 200647657. +738043899 = 706487987 bor 200647657. +568952154 = 706487987 bxor 200647657. +-1020784379 = -341279985 band -1015310939. +-335806545 = -341279985 bor -1015310939. +684977834 = -341279985 bxor -1015310939. +-2135908063 = -1510229717 band -2001410271. +-1375731925 = -1510229717 bor -2001410271. +760176138 = -1510229717 bxor -2001410271. +1104319493 = 1845148935 band 1104663645. +1845493087 = 1845148935 bor 1104663645. +741173594 = 1845148935 bxor 1104663645. +4194305 = 670835363 band 138565977. +805207035 = 670835363 bor 138565977. +801012730 = 670835363 bxor 138565977. +-1054605291 = -316389889 band -1019858411. +-281643009 = -316389889 bor -1019858411. +772962282 = -316389889 bxor -1019858411. +-2113912303 = -1434369253 band -2108368239. +-1428825189 = -1434369253 bor -2108368239. +685087114 = -1434369253 bxor -2108368239. +1103267013 = 1709635063 band 1138462413. +1744830463 = 1709635063 bor 1138462413. +641563450 = 1709635063 bxor 1138462413. +9063041 = 613087891 band 43993801. +648018651 = 613087891 bor 43993801. +638955610 = 613087891 bxor 43993801. +-952072059 = -278876945 band -943142267. +-269947153 = -278876945 bor -943142267. +682124906 = -278876945 bxor -943142267. +-2146433023 = -1590351605 band -1940878847. +-1384797429 = -1590351605 bor -1940878847. +761635594 = -1590351605 bxor -1940878847. +1107968037 = 1787513575 band 1178256701. +1857802239 = 1787513575 bor 1178256701. +749834202 = 1787513575 bxor 1178256701. +85141505 = 657960579 band 227768377. +800587451 = 657960579 bor 227768377. +715445946 = 657960579 bxor 227768377. +-1054339371 = -507727905 band -987078923. +-440467457 = -507727905 bor -987078923. +613871914 = -507727905 bxor -987078923. +-2147065743 = -1603900677 band -2096171663. +-1553006597 = -1603900677 bor -2096171663. +594059146 = -1603900677 bxor -2096171663. +1074017157 = 1747368919 band 1154250669. +1827602431 = 1747368919 bor 1154250669. +753585274 = 1747368919 bxor 1154250669. +18948129 = 556875379 band 191226281. +729153531 = 556875379 bor 191226281. +710205402 = 556875379 bxor 191226281. +-921612731 = -380154161 band -888017051. +-346558481 = -380154161 bor -888017051. +575054250 = -380154161 bxor -888017051. +-2145122079 = -1608251157 band -1967711007. +-1430840085 = -1608251157 bor -1967711007. +714281994 = -1608251157 bxor -1967711007. +1210056709 = 1756907719 band 1327998493. +1874849503 = 1756907719 bor 1327998493. +664792794 = 1756907719 bxor 1327998493. +201622017 = 761703011 band 236816153. +796897147 = 761703011 bor 236816153. +595275130 = 761703011 bxor 236816153. +-1073346155 = -519075393 band -990479403. +-436208641 = -519075393 bor -990479403. +637137514 = -519075393 bxor -990479403. +-1976565679 = -1438842149 band -1892679599. +-1354956069 = -1438842149 bor -1892679599. +621609610 = -1438842149 bxor -1892679599. +1084379269 = 1677652407 band 1218662541. +1811935679 = 1677652407 bor 1218662541. +727556410 = 1677652407 bxor 1218662541. +8413185 = 545714771 band 125921417. +663223003 = 545714771 bor 125921417. +654809818 = 545714771 bxor 125921417. +-939261947 = -377200465 band -904985531. +-342924049 = -377200465 bor -904985531. +596337898 = -377200465 bxor -904985531. +-2147477311 = -1438623541 band -2078236735. +-1369382965 = -1438623541 bor -2078236735. +778094346 = -1438623541 bxor -2078236735. +1213216421 = 1870247591 band 1213626109. +1870657279 = 1870247591 bor 1213626109. +657440858 = 1870247591 bxor 1213626109. +150996033 = 687937091 band 152602105. +689543163 = 687937091 bor 152602105. +538547130 = 687937091 bxor 152602105. +-921665387 = -384511073 band -850229067. +-313074753 = -384511073 bor -850229067. +608590634 = -384511073 bxor -850229067. +-2073228751 = -1384314181 band -2064647375. +-1375732805 = -1384314181 bor -2064647375. +697495946 = -1384314181 bxor -2064647375. +1207963909 = 1852282775 band 1226316141. +1870635007 = 1852282775 bor 1226316141. +662671098 = 1852282775 bxor 1226316141. +67114529 = 788796979 band 69853033. +791535483 = 788796979 bor 69853033. +724420954 = 788796979 bxor 69853033. +-916979707 = -337649009 band -847771355. +-268440657 = -337649009 bor -847771355. +648539050 = -337649009 bxor -847771355. +-2147479391 = -1560143701 band -2067459423. +-1480123733 = -1560143701 bor -2067459423. +667355658 = -1560143701 bxor -2067459423. +1095177349 = 1640469639 band 1233074141. +1778366431 = 1640469639 bor 1233074141. +683189082 = 1640469639 bxor 1233074141. +3960833 = 612299299 band 163345625. +771684091 = 612299299 bor 163345625. +767723258 = 612299299 bxor 163345625. +-1060862699 = -473657985 band -990476907. +-403272193 = -473657985 bor -990476907. +657590506 = -473657985 bxor -990476907. +-1970896367 = -1415675237 band -1903761903. +-1348540773 = -1415675237 bor -1903761903. +622355594 = -1415675237 bxor -1903761903. +1212186693 = 1750642039 band 1273156173. +1811611519 = 1750642039 bor 1273156173. +599424826 = 1750642039 bxor 1273156173. +513 = 622897683 band 177686089. +800583259 = 622897683 bor 177686089. +800582746 = 622897683 bxor 177686089. +-939469819 = -396241809 band -905642491. +-362414481 = -396241809 bor -905642491. +577055338 = -396241809 bxor -905642491. +-2134884223 = -1444853621 band -2065926783. +-1375896181 = -1444853621 bor -2065926783. +758988042 = -1444853621 bxor -2065926783. +1176100901 = 1855578727 band 1180297405. +1859775231 = 1855578727 bor 1180297405. +683674330 = 1855578727 bxor 1180297405. +104862209 = 643317251 band 121721785. +660176827 = 643317251 bor 121721785. +555314618 = 643317251 bxor 121721785. +-971885995 = -417941665 band -828738955. +-274794625 = -417941665 bor -828738955. +697091370 = -417941665 bxor -828738955. +-2113388431 = -1575392645 band -2110996239. +-1573000453 = -1575392645 bor -2110996239. +540387978 = -1575392645 bxor -2110996239. +1116353285 = 1858745175 band 1119583021. +1861974911 = 1858745175 bor 1119583021. +745621626 = 1858745175 bxor 1119583021. +36129 = 659860979 band 105769. +659930619 = 659860979 bor 105769. +659894490 = 659860979 bxor 105769. +-1073733051 = -486394289 band -1066540315. +-479201553 = -486394289 bor -1066540315. +594531498 = -486394289 bxor -1066540315. +-2011903903 = -1437210517 band -2002859935. +-1428166549 = -1437210517 bor -2002859935. +583737354 = -1437210517 bxor -2002859935. +1082687493 = 1625858119 band 1319012765. +1862183391 = 1625858119 bor 1319012765. +779495898 = 1625858119 bxor 1319012765. +270465 = 553974243 band 81732249. +635436027 = 553974243 bor 81732249. +635165562 = 553974243 bxor 81732249. +-1073594091 = -452767425 band -923381931. +-302555265 = -452767425 bor -923381931. +771038826 = -452767425 bxor -923381931. +-2113830319 = -1436171685 band -2112255023. +-1434596389 = -1436171685 bor -2112255023. +679233930 = -1436171685 bxor -2112255023. +1242562565 = 1790191927 band 1264194573. +1811823935 = 1790191927 bor 1264194573. +569261370 = 1790191927 bxor 1264194573. +67117057 = 639115731 band 94430217. +666428891 = 639115731 bor 94430217. +599311834 = 639115731 bxor 94430217. +-920125435 = -340195281 band -848644155. +-268714001 = -340195281 bor -848644155. +651411434 = -340195281 bxor -848644155. +-2143025087 = -1411909557 band -2143024319. +-1411908789 = -1411909557 bor -2143024319. +731116298 = -1411909557 bxor -2143024319. +1308690981 = 1873530407 band 1308957309. +1873796735 = 1873530407 bor 1308957309. +565105754 = 1873530407 bxor 1308957309. +13443393 = 587015619 band 30269817. +603842043 = 587015619 bor 30269817. +590398650 = 587015619 bxor 30269817. +-897443819 = -343778529 band -826139595. +-272474305 = -343778529 bor -826139595. +624969514 = -343778529 bxor -826139595. +-2004811215 = -1443132869 band -1937422671. +-1375744325 = -1443132869 bor -1937422671. +629066890 = -1443132869 bxor -1937422671. +1090948101 = 1628344087 band 1333173485. +1870569471 = 1628344087 bor 1333173485. +779621370 = 1628344087 bxor 1333173485. +144769185 = 769852851 band 145562345. +770646011 = 769852851 bor 145562345. +625876826 = 769852851 bxor 145562345. +-936228859 = -293713393 band -910984027. +-268468561 = -293713393 bor -910984027. +667760298 = -293713393 bxor -910984027. +-2147207135 = -1579190229 band -2012987871. +-1444970965 = -1579190229 bor -2012987871. +702236170 = -1579190229 bxor -2012987871. +1279330309 = 1843096583 band 1279630173. +1843396447 = 1843096583 bor 1279630173. +564066138 = 1843096583 bxor 1279630173. +32769 = 649642403 band 155553881. +805163515 = 649642403 bor 155553881. +805130746 = 649642403 bxor 155553881. +-998125547 = -460598017 band -961160939. +-423633409 = -460598017 bor -961160939. +574492138 = -460598017 bxor -961160939. +-2113748975 = -1571634661 band -1951927919. +-1409813605 = -1571634661 bor -1951927919. +703935370 = -1571634661 bxor -1951927919. +1086391493 = 1657890039 band 1154029005. +1725527551 = 1657890039 bor 1154029005. +639136058 = 1657890039 bxor 1154029005. +34357633 = 657283475 band 39731657. +662657499 = 657283475 bor 39731657. +628299866 = 657283475 bxor 39731657. +-1040174715 = -481690641 band -905956987. +-347472913 = -481690641 bor -905956987. +692701802 = -481690641 bxor -905956987. +-2012979199 = -1411094517 band -2011733759. +-1409849077 = -1411094517 bor -2011733759. +603130122 = -1411094517 bxor -2011733759. +1208485925 = 1785690599 band 1293421629. +1870626303 = 1785690599 bor 1293421629. +662140378 = 1785690599 bxor 1293421629. +36572417 = 581946755 band 41824057. +587198395 = 581946755 bor 41824057. +550625978 = 581946755 bxor 41824057. +-1040087851 = -434651425 band -1014397451. +-408961025 = -434651425 bor -1014397451. +631126826 = -434651425 bxor -1014397451. +-2136930191 = -1595708933 band -2051437455. +-1510216197 = -1595708933 bor -2051437455. +626713994 = -1595708933 bxor -2051437455. +1275079301 = 1827973847 band 1292467885. +1845362431 = 1827973847 bor 1292467885. +570283130 = 1827973847 bxor 1292467885. +107747361 = 644816243 band 132929705. +669998587 = 644816243 bor 132929705. +562251226 = 644816243 bxor 132929705. +-838855611 = -300671537 band -821504411. +-283320337 = -300671537 bor -821504411. +555535274 = -300671537 bxor -821504411. +-2079046687 = -1520515093 band -2068483103. +-1509951509 = -1520515093 bor -2068483103. +569095178 = -1520515093 bxor -2068483103. +1075078405 = 1616902087 band 1077177629. +1619001311 = 1616902087 bor 1077177629. +543922906 = 1616902087 bxor 1077177629. +657409 = 693782883 band 11517465. +704642939 = 693782883 bor 11517465. +703985530 = 693782883 bxor 11517465. +-1038876523 = -501344065 band -1007344939. +-469812481 = -501344065 bor -1007344939. +569064042 = -501344065 bxor -1007344939. +-1944059567 = -1356496421 band -1930291375. +-1342728229 = -1356496421 bor -1930291375. +601331338 = -1356496421 bxor -1930291375. +1080049797 = 1752195255 band 1173346189. +1845491647 = 1752195255 bor 1173346189. +765441850 = 1752195255 bxor 1173346189. +134238465 = 740315475 band 177168265. +783245275 = 740315475 bor 177168265. +649006810 = 740315475 bxor 177168265. +-997971195 = -288051281 band -981111995. +-271192081 = -288051281 bor -981111995. +726779114 = -288051281 bxor -981111995. +-2079975743 = -1513711669 band -1911130431. +-1344866357 = -1513711669 bor -1911130431. +735109386 = -1513711669 bxor -1911130431. +1073784229 = 1722082727 band 1095941629. +1744240127 = 1722082727 bor 1095941629. +670455898 = 1722082727 bxor 1095941629. +17839169 = 691025219 band 51526905. +724712955 = 691025219 bor 51526905. +706873786 = 691025219 bxor 51526905. +-1030708587 = -426319201 band -1028608075. +-424218689 = -426319201 bor -1028608075. +606489898 = -426319201 bxor -1028608075. +-2105475023 = -1567553093 band -1886809551. +-1348887621 = -1567553093 bor -1886809551. +756587402 = -1567553093 bxor -1886809551. +1211367429 = 1782351511 band 1228152941. +1799137023 = 1782351511 bor 1228152941. +587769594 = 1782351511 bxor 1228152941. +70800417 = 616101171 band 125785705. +671086459 = 616101171 bor 125785705. +600286042 = 616101171 bxor 125785705. +-1073631227 = -511463025 band -970067931. +-407899729 = -511463025 bor -970067931. +665731498 = -511463025 bxor -970067931. +-2146287199 = -1600923733 band -2139985503. +-1594622037 = -1600923733 bor -2139985503. +551665162 = -1600923733 bxor -2139985503. +1075987077 = 1614168967 band 1210777309. +1748959199 = 1614168967 bor 1210777309. +672972122 = 1614168967 bxor 1210777309. +76120321 = 749310243 band 81636313. +754826235 = 749310243 bor 81636313. +678705914 = 749310243 bxor 81636313. +-999289835 = -310764417 band -965464939. +-276939521 = -310764417 bor -965464939. +722350314 = -310764417 bxor -965464939. +-2070544111 = -1398931045 band -2017985263. +-1346372197 = -1398931045 bor -2017985263. +724171914 = -1398931045 bxor -2017985263. +1073748037 = 1666260087 band 1284397389. +1876909439 = 1666260087 bor 1284397389. +803161402 = 1666260087 bxor 1284397389. +11536641 = 682690835 band 133446985. +804601179 = 682690835 bor 133446985. +793064538 = 682690835 bxor 133446985. +-1005051643 = -300342417 band -977640187. +-272930961 = -300342417 bor -977640187. +732120682 = -300342417 bxor -977640187. +-2080373631 = -1522628725 band -2080289663. +-1522544757 = -1522628725 bor -2080289663. +557828874 = -1522628725 bxor -2080289663. +1208221989 = 1812730215 band 1215639485. +1820147711 = 1812730215 bor 1215639485. +611925722 = 1812730215 bxor 1215639485. +134875137 = 708730115 band 222956217. +796811195 = 708730115 bor 222956217. +661936058 = 708730115 bxor 222956217. +-1061715883 = -322976161 band -1040737931. +-301998209 = -322976161 bor -1040737931. +759717674 = -322976161 bxor -1040737931. +-1971043983 = -1429968517 band -1951049743. +-1409974277 = -1429968517 bor -1951049743. +561069706 = -1429968517 bxor -1951049743. +1084621317 = 1621500503 band 1102479917. +1639359103 = 1621500503 bor 1102479917. +554737786 = 1621500503 bxor 1102479917. +1057 = 746622195 band 19272745. +765893883 = 746622195 bor 19272745. +765892826 = 746622195 bxor 19272745. +-1065352891 = -393411249 band -991770139. +-319828497 = -393411249 bor -991770139. +745524394 = -393411249 bxor -991770139. +-1942354079 = -1354848405 band -1929699487. +-1342193813 = -1354848405 bor -1929699487. +600160266 = -1354848405 bxor -1929699487. +1091059717 = 1696485191 band 1105809565. +1711235039 = 1696485191 bor 1105809565. +620175322 = 1696485191 bxor 1105809565. +67508353 = 610703587 band 261052825. +804248059 = 610703587 bor 261052825. +736739706 = 610703587 bxor 261052825. +-1034756075 = -429924289 band -1007487403. +-402655617 = -429924289 bor -1007487403. +632100458 = -429924289 bxor -1007487403. +-2076704687 = -1501806245 band -1917213999. +-1342315557 = -1501806245 bor -1917213999. +734389130 = -1501806245 bxor -1917213999. +1109432325 = 1798543415 band 1180998413. +1870109503 = 1798543415 bor 1180998413. +760677178 = 1798543415 bxor 1180998413. +819201 = 547324115 band 72145673. +618650587 = 547324115 bor 72145673. +617831386 = 547324115 bxor 72145673. +-1068034555 = -522758353 band -1067508027. +-522231825 = -522758353 bor -1067508027. +545802730 = -522758353 bxor -1067508027. +-2113658303 = -1509148853 band -1952980415. +-1348470965 = -1509148853 bor -1952980415. +765187338 = -1509148853 bxor -1952980415. +1076125989 = 1650785575 band 1077895549. +1652555135 = 1650785575 bor 1077895549. +576429146 = 1650785575 bxor 1077895549. +142606401 = 697976003 band 182818937. +738188539 = 697976003 bor 182818937. +595582138 = 697976003 bxor 182818937. +-1072545259 = -397252065 band -954318027. +-279024833 = -397252065 bor -954318027. +793520426 = -397252065 bxor -954318027. +-2126739151 = -1522693829 band -1946362447. +-1342317125 = -1522693829 bor -1946362447. +784422026 = -1522693829 bxor -1946362447. +1146102277 = 1743879703 band 1146135533. +1743912959 = 1743879703 bor 1146135533. +597810682 = 1743879703 bxor 1146135533. +8421537 = 562422963 band 245404137. +799405563 = 562422963 bor 245404137. +790984026 = 562422963 bxor 245404137. +-1059061499 = -487581425 band -1058577499. +-487097425 = -487581425 bor -1058577499. +571964074 = -487581425 bxor -1058577499. +-1945168607 = -1390463189 band -1945135839. +-1390430421 = -1390463189 bor -1945135839. +554738186 = -1390463189 bxor -1945135839. +1107821061 = 1725438727 band 1261396573. +1879014239 = 1725438727 bor 1261396573. +771193178 = 1725438727 bxor 1261396573. +16385 = 609312931 band 176473945. +785770491 = 609312931 bor 176473945. +785754106 = 609312931 bxor 176473945. +-1073676267 = -326147073 band -1036943339. +-289414145 = -326147073 bor -1036943339. +784262122 = -326147073 bxor -1036943339. +-2139095023 = -1467989733 band -2135488367. +-1464383077 = -1467989733 bor -2135488367. +674711946 = -1467989733 bxor -2135488367. +1091735749 = 1742197751 band 1093835981. +1744297983 = 1742197751 bor 1093835981. +652562234 = 1742197751 bxor 1093835981. +17381505 = 665565331 band 156842185. +805026011 = 665565331 bor 156842185. +787644506 = 665565331 bxor 156842185. +-1039988603 = -422622481 band -885811067. +-268444945 = -422622481 bor -885811067. +771543658 = -422622481 bxor -885811067. +-2104877055 = -1544575221 band -2036713471. +-1476411637 = -1544575221 bor -2036713471. +628465418 = -1544575221 bxor -2036713471. +1080098853 = 1634707687 band 1181831997. +1736440831 = 1634707687 bor 1181831997. +656341978 = 1634707687 bxor 1181831997. +16835585 = 721677443 band 94692921. +799534779 = 721677443 bor 94692921. +782699194 = 721677443 bxor 94692921. +-1056666411 = -384905761 band -941314827. +-269554177 = -384905761 bor -941314827. +787112234 = -384905761 bxor -941314827. +-2145378191 = -1380161285 band -2111822991. +-1346606085 = -1380161285 bor -2111822991. +798772106 = -1380161285 bxor -2111822991. +1187152261 = 1742641623 band 1321371053. +1876860415 = 1742641623 bor 1321371053. +689708154 = 1742641623 bxor 1321371053. +25742369 = 663288947 band 162451369. +799997947 = 663288947 bor 162451369. +774255578 = 663288947 bxor 162451369. +-1066881979 = -529732401 band -805585563. +-268435985 = -529732401 bor -805585563. +798445994 = -529732401 bxor -805585563. +-2056944927 = -1510635797 band -1888498975. +-1342189845 = -1510635797 bor -1888498975. +714755082 = -1510635797 bxor -1888498975. +1092690949 = 1831052999 band 1102918685. +1841280735 = 1831052999 bor 1102918685. +748589786 = 1831052999 bxor 1102918685. +2744321 = 539617379 band 259912985. +796786043 = 539617379 bor 259912985. +794041722 = 539617379 bxor 259912985. +-959938155 = -272062529 band -957363755. +-269488129 = -272062529 bor -957363755. +690450026 = -272062529 bxor -957363755. +-2107637679 = -1368784677 band -2106577327. +-1367724325 = -1368784677 bor -2106577327. +739913354 = -1368784677 bxor -2106577327. +1085820549 = 1627246519 band 1253596813. +1795022783 = 1627246519 bor 1253596813. +709202234 = 1627246519 bxor 1253596813. +9506817 = 563458131 band 14243465. +568194779 = 563458131 bor 14243465. +558687962 = 563458131 bxor 14243465. +-876555771 = -272564561 band -872951227. +-268960017 = -272564561 bor -872951227. +607595754 = -272564561 bxor -872951227. +-2104998719 = -1431775541 band -2033693247. +-1360470069 = -1431775541 bor -2033693247. +744528650 = -1431775541 bxor -2033693247. +1086850213 = 1626084519 band 1221264637. +1760498943 = 1626084519 bor 1221264637. +673648730 = 1626084519 bxor 1221264637. +33771585 = 574313539 band 122156025. +662697979 = 574313539 bor 122156025. +628926394 = 574313539 bxor 122156025. +-905916267 = -290131553 band -905259339. +-289474625 = -290131553 bor -905259339. +616441642 = -290131553 bxor -905259339. +-2147416015 = -1610544965 band -1881200335. +-1344329285 = -1610544965 bor -1881200335. +803086730 = -1610544965 bxor -1881200335. +1208755461 = 1747809687 band 1322002285. +1861056511 = 1747809687 bor 1322002285. +652301050 = 1747809687 bxor 1322002285. +50209 = 575263795 band 202427753. +777641339 = 575263795 bor 202427753. +777591130 = 575263795 bxor 202427753. +-1060929531 = -524058481 band -941631707. +-404760657 = -524058481 bor -941631707. +656168874 = -524058481 bxor -941631707. +-2138996575 = -1518233941 band -1998864223. +-1378101589 = -1518233941 bor -1998864223. +760894986 = -1518233941 bxor -1998864223. +1128317061 = 1874915975 band 1129498077. +1876096991 = 1874915975 bor 1129498077. +747779930 = 1874915975 bxor 1129498077. +137371649 = 732966947 band 138076889. +733672187 = 732966947 bor 138076889. +596300538 = 732966947 bxor 138076889. +-943095019 = -271864961 band -940715115. +-269485057 = -271864961 bor -940715115. +673609962 = -271864961 bxor -940715115. +-2136932335 = -1543929701 band -2069556207. +-1476553573 = -1543929701 bor -2069556207. +660378762 = -1543929701 bxor -2069556207. +1076199493 = 1852148599 band 1085661261. +1861610367 = 1852148599 bor 1085661261. +785410874 = 1852148599 bxor 1085661261. +860161 = 572352531 band 76362825. +647855195 = 572352531 bor 76362825. +646995034 = 572352531 bxor 76362825. +-932691963 = -345214353 band -932459515. +-344981905 = -345214353 bor -932459515. +587710058 = -345214353 bxor -932459515. +-2048785791 = -1510488437 band -1914559615. +-1376262261 = -1510488437 bor -1914559615. +672523530 = -1510488437 bxor -1914559615. +1074282533 = 1754939495 band 1158444733. +1839101695 = 1754939495 bor 1158444733. +764819162 = 1754939495 bxor 1158444733. +16793601 = 587234307 band 160350649. +730791355 = 587234307 bor 160350649. +713997754 = 587234307 bxor 160350649. +-1056915371 = -385559201 band -1018118027. +-346761857 = -385559201 bor -1018118027. +710153514 = -385559201 bxor -1018118027. +-2033620879 = -1479841669 band -2030440719. +-1476661509 = -1479841669 bor -2030440719. +556959370 = -1479841669 bxor -2030440719. +1074528517 = 1620971863 band 1110280493. +1656723839 = 1620971863 bor 1110280493. +582195322 = 1620971863 bxor 1110280493. +92277537 = 629697523 band 260475689. +797895675 = 629697523 bor 260475689. +705618138 = 629697523 bxor 260475689. +-1038905275 = -474753969 band -833376027. +-269224721 = -474753969 bor -833376027. +769680554 = -474753969 bxor -833376027. +-2113706399 = -1484560789 band -1978435999. +-1349290389 = -1484560789 bor -1978435999. +764416010 = -1484560789 bxor -1978435999. +1142953477 = 1718615623 band 1303386013. +1879048159 = 1718615623 bor 1303386013. +736094682 = 1718615623 bxor 1303386013. +169873537 = 715405283 band 242978969. +788510715 = 715405283 bor 242978969. +618637178 = 715405283 bxor 242978969. +-934802155 = -329748673 band -890528427. +-285474945 = -329748673 bor -890528427. +649327210 = -329748673 bxor -890528427. +-2147188655 = -1527857061 band -1995064879. +-1375733285 = -1527857061 bor -1995064879. +771455370 = -1527857061 bxor -1995064879. +1087046149 = 1741621047 band 1089151501. +1743726399 = 1741621047 bor 1089151501. +656680250 = 1741621047 bxor 1089151501. +201380353 = 755163091 band 238342665. +792125403 = 755163091 bor 238342665. +590745050 = 755163091 bxor 238342665. +-1073642491 = -376330705 band -967866939. +-270555153 = -376330705 bor -967866939. +803087338 = -376330705 bxor -967866939. +-2122043327 = -1583581621 band -1918387903. +-1379926197 = -1583581621 bor -1918387903. +742117130 = -1583581621 bxor -1918387903. +1076897829 = 1614425127 band 1224059005. +1761586303 = 1614425127 bor 1224059005. +684688474 = 1614425127 bxor 1224059005. +1131329 = 554918851 band 104419193. +658206715 = 554918851 bor 104419193. +657075386 = 554918851 bxor 104419193. +-1053399019 = -406947553 band -914986443. +-268534977 = -406947553 bor -914986443. +784864042 = -406947553 bxor -914986443. +-2146435023 = -1596225477 band -1993313103. +-1443103557 = -1596225477 bor -1993313103. +703331466 = -1596225477 bxor -1993313103. +1084237829 = 1760587031 band 1185327853. +1861677055 = 1760587031 bor 1185327853. +777439226 = 1760587031 bxor 1185327853. +83886241 = 621069235 band 231737577. +768920571 = 621069235 bor 231737577. +685034330 = 621069235 bxor 231737577. +-938129403 = -386013169 band -921220443. +-369104209 = -386013169 bor -921220443. +569025194 = -386013169 bxor -921220443. +-2070748127 = -1480919509 band -2066289631. +-1476461013 = -1480919509 bor -2066289631. +594287114 = -1480919509 bxor -2066289631. +1217398789 = 1760610823 band 1318398301. +1861610335 = 1760610823 bor 1318398301. +644211546 = 1760610823 bxor 1318398301. +12975617 = 549846947 band 201326169. +738197499 = 549846947 bor 201326169. +725221882 = 549846947 bxor 201326169. +-987225579 = -449907969 band -978770155. +-441452545 = -449907969 bor -978770155. +545773034 = -449907969 bxor -978770155. +-2130706415 = -1391869925 band -2122178671. +-1383342181 = -1391869925 bor -2122178671. +747364234 = -1391869925 bxor -2122178671. +1075315397 = 1694122743 band 1226318797. +1845126143 = 1694122743 bor 1226318797. +769810746 = 1694122743 bxor 1226318797. +100665217 = 637933459 band 126889929. +664158171 = 637933459 bor 126889929. +563492954 = 637933459 bxor 126889929. +-916416123 = -370107921 band -882704507. +-336396305 = -370107921 bor -882704507. +580019818 = -370107921 bxor -882704507. +-2125462015 = -1453922805 band -2015817983. +-1344278773 = -1453922805 bor -2015817983. +781183242 = -1453922805 bxor -2015817983. +1107464741 = 1871435751 band 1111923261. +1875894271 = 1871435751 bor 1111923261. +768429530 = 1871435751 bxor 1111923261. +264449 = 540281731 band 117939513. +657956795 = 540281731 bor 117939513. +657692346 = 540281731 bxor 117939513. +-1037971243 = -358490913 band -1036266507. +-356786177 = -358490913 bor -1036266507. +681185066 = -358490913 bxor -1036266507. +-2143280527 = -1494128645 band -2008892815. +-1359740933 = -1494128645 bor -2008892815. +783539594 = -1494128645 bxor -2008892815. +1222936709 = 1759807703 band 1240960173. +1777831167 = 1759807703 bor 1240960173. +554894458 = 1759807703 bxor 1240960173. +2900513 = 612293491 band 11355817. +620748795 = 612293491 bor 11355817. +617848282 = 612293491 bxor 11355817. +-1067409339 = -530465841 band -840260507. +-303317009 = -530465841 bor -840260507. +764092330 = -530465841 bxor -840260507. +-2132803103 = -1578613269 band -1964629535. +-1410439701 = -1578613269 bor -1964629535. +722363402 = -1578613269 bxor -1964629535. +1124159749 = 1862489543 band 1136786205. +1875115999 = 1862489543 bor 1136786205. +750956250 = 1862489543 bxor 1136786205. +8389633 = 567641955 band 176696345. +735948667 = 567641955 bor 176696345. +727559034 = 567641955 bxor 176696345. +-939118443 = -368101697 band -840535851. +-269519105 = -368101697 bor -840535851. +669599338 = -368101697 bxor -840535851. +-2012592815 = -1475706917 band -1884666543. +-1347780645 = -1475706917 bor -1884666543. +664812170 = -1475706917 bxor -1884666543. +1151607941 = 1839677111 band 1190978957. +1879048127 = 1839677111 bor 1190978957. +727440186 = 1839677111 bxor 1190978957. +4656385 = 552013651 band 174017929. +721375195 = 552013651 bor 174017929. +716718810 = 552013651 bxor 174017929. +-868218619 = -330740305 band -848938683. +-311460369 = -330740305 bor -848938683. +556758250 = -330740305 bxor -848938683. +-2010774335 = -1461250613 band -1909054271. +-1359530549 = -1461250613 bor -1909054271. +651243786 = -1461250613 bxor -1909054271. +1309623205 = 1850688423 band 1321159677. +1862224895 = 1850688423 bor 1321159677. +552601690 = 1850688423 bxor 1321159677. +69214785 = 606237507 band 96054009. +633076731 = 606237507 bor 96054009. +563861946 = 606237507 bxor 96054009. +-1050673003 = -512819041 band -1017053771. +-479199809 = -512819041 bor -1017053771. +571473194 = -512819041 bxor -1017053771. +-2051014607 = -1513289797 band -2047819727. +-1510094917 = -1513289797 bor -2047819727. +540919690 = -1513289797 bxor -2047819727. +1210065925 = 1748657303 band 1239428717. +1778020095 = 1748657303 bor 1239428717. +567954170 = 1748657303 bxor 1239428717. +26607649 = 666284851 band 31343721. +671020923 = 666284851 bor 31343721. +644413274 = 666284851 bxor 31343721. +-1064497659 = -375435377 band -1030898139. +-341835857 = -375435377 bor -1030898139. +722661802 = -375435377 bxor -1030898139. +-2147412575 = -1580509781 band -1912531039. +-1345628245 = -1580509781 bor -1912531039. +801784330 = -1580509781 bxor -1912531039. +1080459397 = 1617404295 band 1257671901. +1794616799 = 1617404295 bor 1257671901. +714157402 = 1617404295 bxor 1257671901. +26216705 = 563269411 band 64231897. +601284603 = 563269411 bor 64231897. +575067898 = 563269411 bxor 64231897. +-937346539 = -356959617 band -916227435. +-335840513 = -356959617 bor -916227435. +601506026 = -356959617 bxor -916227435. +-2130695407 = -1582235749 band -2058474735. +-1510015077 = -1582235749 bor -2058474735. +620680330 = -1582235749 bxor -2058474735. +1209098821 = 1771436663 band 1213818701. +1776156543 = 1771436663 bor 1213818701. +567057722 = 1771436663 bxor 1213818701. +6292225 = 560318227 band 6433609. +560459611 = 560318227 bor 6433609. +554167386 = 560318227 bxor 6433609. +-1072103163 = -530857617 band -1038535931. +-497290385 = -530857617 bor -1038535931. +574812778 = -530857617 bxor -1038535931. +-2146697087 = -1408432757 band -2105607551. +-1367343221 = -1408432757 bor -2105607551. +779353866 = -1408432757 bxor -2105607551. +1141124389 = 1682206567 band 1277148605. +1818230783 = 1682206567 bor 1277148605. +677106394 = 1682206567 bxor 1277148605. +923649 = 547265283 band 202340537. +748682171 = 547265283 bor 202340537. +747758522 = 547265283 bxor 202340537. +-1029315499 = -337255329 band -1029314699. +-337254529 = -337255329 bor -1029314699. +692060970 = -337255329 bxor -1029314699. +-2127952527 = -1456576645 band -2080733711. +-1409357829 = -1456576645 bor -2080733711. +718594698 = -1456576645 bxor -2080733711. +1142947845 = 1857159255 band 1142984749. +1857196159 = 1857159255 bor 1142984749. +714248314 = 1857159255 bxor 1142984749. +35652129 = 577522419 band 186843689. +728713979 = 577522419 bor 186843689. +693061850 = 577522419 bxor 186843689. +-1002405051 = -461986993 band -859793435. +-319375377 = -461986993 bor -859793435. +683029674 = -461986993 bxor -859793435. +-2094791327 = -1557912213 band -1880634015. +-1343754901 = -1557912213 bor -1880634015. +751036426 = -1557912213 bxor -1880634015. +1087409157 = 1692249415 band 1106435741. +1711275999 = 1692249415 bor 1106435741. +623866842 = 1692249415 bxor 1106435741. +27379329 = 599643875 band 27510681. +599775227 = 599643875 bor 27510681. +572395898 = 599643875 bxor 27510681. +-991935467 = -420676033 band -840940459. +-269681025 = -420676033 bor -840940459. +722254442 = -420676033 bxor -840940459. +-2077421487 = -1514324133 band -2077372207. +-1514274853 = -1514324133 bor -2077372207. +563146634 = -1514324133 bxor -2077372207. +1082400773 = 1619424823 band 1257089293. +1794113343 = 1619424823 bor 1257089293. +711712570 = 1619424823 bxor 1257089293. +54528001 = 725761747 band 56150281. +727384027 = 725761747 bor 56150281. +672856026 = 725761747 bxor 56150281. +-987503611 = -437783249 band -818156347. +-268435985 = -437783249 bor -818156347. +719067626 = -437783249 bxor -818156347. +-2046783423 = -1366772405 band -2039246783. +-1359235765 = -1366772405 bor -2039246783. +687547658 = -1366772405 bxor -2039246783. +1210272549 = 1764449063 band 1210576765. +1764753279 = 1764449063 bor 1210576765. +554480730 = 1764449063 bxor 1210576765. +21496385 = 694715075 band 63506041. +736724731 = 694715075 bor 63506041. +715228346 = 694715075 bxor 63506041. +-1044217835 = -372864993 band -976580299. +-305227457 = -372864993 bor -976580299. +738990378 = -372864993 bxor -976580299. +-2080373967 = -1395292357 band -2078274639. +-1393193029 = -1395292357 bor -2078274639. +687180938 = -1395292357 bxor -2078274639. +1141379077 = 1678466071 band 1182314989. +1719401983 = 1678466071 bor 1182314989. +578022906 = 1678466071 bxor 1182314989. +1778337 = 677356211 band 104562665. +780140539 = 677356211 bor 104562665. +778362202 = 677356211 bxor 104562665. +-1073532667 = -525879537 band -1035783771. +-488130641 = -525879537 bor -1035783771. +585402026 = -525879537 bxor -1035783771. +-2146303711 = -1582123733 band -2108013791. +-1543833813 = -1582123733 bor -2108013791. +602469898 = -1582123733 bxor -2108013791. +1143238661 = 1680177415 band 1182199901. +1719138655 = 1680177415 bor 1182199901. +575899994 = 1680177415 bxor 1182199901. +202773505 = 739679907 band 230110553. +767016955 = 739679907 bor 230110553. +564243450 = 739679907 bxor 230110553. +-1073184747 = -295009793 band -1055076843. +-276901889 = -295009793 bor -1055076843. +796282858 = -295009793 bxor -1055076843. +-1911998959 = -1343275237 band -1911998831. +-1343275109 = -1343275237 bor -1911998831. +568723850 = -1343275237 bxor -1911998831. +1211670725 = 1782100471 band 1283041997. +1853471743 = 1782100471 bor 1283041997. +641801018 = 1782100471 bxor 1283041997. +9857 = 574387859 band 218310345. +792688347 = 574387859 bor 218310345. +792678490 = 574387859 bxor 218310345. +-930324347 = -324146961 band -896637307. +-290459921 = -324146961 bor -896637307. +639864426 = -324146961 bxor -896637307. +-2012077055 = -1407572725 band -1949047295. +-1344542965 = -1407572725 bor -1949047295. +667534090 = -1407572725 bxor -1949047295. +1082392613 = 1690568423 band 1083695421. +1691871231 = 1690568423 bor 1083695421. +609478618 = 1690568423 bxor 1083695421. +33554433 = 574630531 band 111563833. +652639931 = 574630531 bor 111563833. +619085498 = 574630531 bxor 111563833. +-1031738667 = -355406881 band -1030817035. +-354485249 = -355406881 bor -1030817035. +677253418 = -355406881 bxor -1030817035. +-2013249423 = -1400740101 band -2011082383. +-1398573061 = -1400740101 bor -2011082383. +614676362 = -1400740101 bxor -2011082383. +1073746821 = 1611036631 band 1319670701. +1856960511 = 1611036631 bor 1319670701. +783213690 = 1611036631 bxor 1319670701. +205568033 = 760265331 band 216513961. +771211259 = 760265331 bor 216513961. +565643226 = 760265331 bxor 216513961. +-925857211 = -302871857 band -925529243. +-302543889 = -302871857 bor -925529243. +623313322 = -302871857 bxor -925529243. +-2129657631 = -1456012053 band -2028439327. +-1354793749 = -1456012053 bor -2028439327. +774863882 = -1456012053 bxor -2028439327. +1145176069 = 1711211719 band 1178780189. +1744815839 = 1711211719 bor 1178780189. +599639770 = 1711211719 bxor 1178780189. +4989441 = 777856611 band 30303001. +803170171 = 777856611 bor 30303001. +798180730 = 777856611 bxor 30303001. +-1060043371 = -521026113 band -925296683. +-386279425 = -521026113 bor -925296683. +673763946 = -521026113 bxor -925296683. +-2080351151 = -1408827685 band -2069865391. +-1398341925 = -1408827685 bor -2069865391. +682009226 = -1408827685 bxor -2069865391. +1244408965 = 1852616119 band 1253928077. +1862135231 = 1852616119 bor 1253928077. +617726266 = 1852616119 bxor 1253928077. +33571841 = 705982035 band 119620745. +792030939 = 705982035 bor 119620745. +758459098 = 705982035 bxor 119620745. +-1069514747 = -462578513 band -909074363. +-302138129 = -462578513 bor -909074363. +767376618 = -462578513 bxor -909074363. +-2147397439 = -1602136885 band -2074084415. +-1528823861 = -1602136885 bor -2074084415. +618573578 = -1602136885 bxor -2074084415. +1108218533 = 1859023527 band 1127191293. +1877996287 = 1859023527 bor 1127191293. +769777754 = 1859023527 bxor 1127191293. +241500225 = 786797123 band 241656313. +786953211 = 786797123 bor 241656313. +545452986 = 786797123 bxor 241656313. +-830405483 = -289075297 band -827120459. +-285790273 = -289075297 bor -827120459. +544615210 = -289075297 bxor -827120459. +-2118908367 = -1544223045 band -2118232271. +-1543546949 = -1544223045 bor -2118232271. +575361418 = -1544223045 bxor -2118232271. +1247809797 = 1784894359 band 1248867693. +1785952255 = 1784894359 bor 1248867693. +538142458 = 1784894359 bxor 1248867693. +15176225 = 620728883 band 149404521. +754957179 = 620728883 bor 149404521. +739780954 = 620728883 bxor 149404521. +-1005124603 = -334029169 band -969431771. +-298336337 = -334029169 bor -969431771. +706788266 = -334029169 bxor -969431771. +-2057304927 = -1519315797 band -1880985951. +-1342996821 = -1519315797 bor -1880985951. +714308106 = -1519315797 bxor -1880985951. +1107447941 = 1646940295 band 1326863325. +1866355679 = 1646940295 bor 1326863325. +758907738 = 1646940295 bxor 1326863325. +100745217 = 777088547 band 128536793. +804880123 = 777088547 bor 128536793. +704134906 = 777088547 bxor 128536793. +-901775083 = -297612929 band -892001899. +-287839745 = -297612929 bor -892001899. +613935338 = -297612929 bxor -892001899. +-2122300911 = -1513849189 band -1984740847. +-1376289125 = -1513849189 bor -1984740847. +746011786 = -1513849189 bxor -1984740847. +1080059973 = 1692559735 band 1131998797. +1744498559 = 1692559735 bor 1131998797. +664438586 = 1692559735 bxor 1131998797. +33694209 = 646587923 band 192094793. +804988507 = 646587923 bor 192094793. +771294298 = 646587923 bxor 192094793. +-1061023739 = -320401297 band -1027433979. +-286811537 = -320401297 bor -1027433979. +774212202 = -320401297 bxor -1027433979. +-2125053823 = -1484897141 band -2116562559. +-1476405877 = -1484897141 bor -2116562559. +648647946 = -1484897141 bxor -2116562559. +1292502053 = 1862966887 band 1303315645. +1873780479 = 1862966887 bor 1303315645. +581278426 = 1862966887 bxor 1303315645. +535041 = 588823043 band 80490425. +668778427 = 588823043 bor 80490425. +668243386 = 588823043 bxor 80490425. +-983432619 = -446500001 band -805892491. +-268959873 = -446500001 bor -805892491. +714472746 = -446500001 bxor -805892491. +-2103114639 = -1360173445 band -2101928719. +-1358987525 = -1360173445 bor -2101928719. +744127114 = -1360173445 bxor -2101928719. +1115784965 = 1793191767 band 1200592685. +1877999487 = 1793191767 bor 1200592685. +762214522 = 1793191767 bxor 1200592685. +52963617 = 590096883 band 66812201. +603945467 = 590096883 bor 66812201. +550981850 = 590096883 bxor 66812201. +-1073647035 = -355110321 band -1071022363. +-352485649 = -355110321 bor -1071022363. +721161386 = -355110321 bxor -1071022363. +-2111822751 = -1574902677 band -1904728991. +-1367808917 = -1574902677 bor -1904728991. +744013834 = -1574902677 bxor -1904728991. +1075905541 = 1617386567 band 1320265117. +1861746143 = 1617386567 bor 1320265117. +785840602 = 1617386567 bxor 1320265117. +151221377 = 800290275 band 151518873. +800587771 = 800290275 bor 151518873. +649366394 = 800290275 bxor 151518873. +-1005549291 = -434270913 band -858723499. +-287445121 = -434270913 bor -858723499. +718104170 = -434270913 bxor -858723499. +-2013157807 = -1461207461 band -1895700527. +-1343750181 = -1461207461 bor -1895700527. +669407626 = -1461207461 bxor -1895700527. +1145577477 = 1700390199 band 1147940877. +1702753599 = 1700390199 bor 1147940877. +557176122 = 1700390199 bxor 1147940877. +51937281 = 727555539 band 62439433. +738057691 = 727555539 bor 62439433. +686120410 = 727555539 bxor 62439433. +-1056948219 = -438680529 band -886811707. +-268544017 = -438680529 bor -886811707. +788404202 = -438680529 bxor -886811707. +-2066717631 = -1395592117 band -2047121599. +-1375996085 = -1395592117 bor -2047121599. +690721546 = -1395592117 bxor -2047121599. +1292894757 = 1832421927 band 1305884285. +1845411455 = 1832421927 bor 1305884285. +552516698 = 1832421927 bxor 1305884285. +43032897 = 580493763 band 60079481. +597540347 = 580493763 bor 60079481. +554507450 = 580493763 bxor 60079481. +-871722987 = -295004385 band -870664139. +-293945537 = -295004385 bor -870664139. +577777450 = -295004385 bxor -870664139. +-2012511695 = -1456765381 band -1932811599. +-1377065285 = -1456765381 bor -1932811599. +635446410 = -1456765381 bxor -1932811599. +1094846469 = 1765952279 band 1137096941. +1808202751 = 1765952279 bor 1137096941. +713356282 = 1765952279 bxor 1137096941. +58884257 = 731283891 band 132314857. +804714491 = 731283891 bor 132314857. +745830234 = 731283891 bxor 132314857. +-932642811 = -370309617 band -865396571. +-303063377 = -370309617 bor -865396571. +629579434 = -370309617 bxor -865396571. +-2147479519 = -1425640405 band -2070308319. +-1348469205 = -1425640405 bor -2070308319. +799010314 = -1425640405 bxor -2070308319. +1079255045 = 1752573959 band 1121236829. +1794555743 = 1752573959 bor 1121236829. +715300698 = 1752573959 bxor 1121236829. +100805633 = 641940899 band 262827097. +803962363 = 641940899 bor 262827097. +703156730 = 641940899 bxor 262827097. +-1073737707 = -398323457 band -997427947. +-322013697 = -398323457 bor -997427947. +751724010 = -398323457 bxor -997427947. +-2147480559 = -1590641125 band -2041819759. +-1484980325 = -1590641125 bor -2041819759. +662500234 = -1590641125 bxor -2041819759. +1125327045 = 1737695479 band 1264005581. +1876374015 = 1737695479 bor 1264005581. +751046970 = 1737695479 bxor 1264005581. +134354305 = 743363987 band 162667977. +771677659 = 743363987 bor 162667977. +637323354 = 743363987 bxor 162667977. +-939195003 = -284739601 band -927609467. +-273154065 = -284739601 bor -927609467. +666040938 = -284739601 bxor -927609467. +-2146950143 = -1405524981 band -2104836863. +-1363411701 = -1405524981 bor -2104836863. +783538442 = -1405524981 bxor -2104836863. +1090527269 = 1628976615 band 1097148477. +1635597823 = 1628976615 bor 1097148477. +545070554 = 1628976615 bxor 1097148477. +2305 = 556288387 band 75565881. +631851963 = 556288387 bor 75565881. +631849658 = 556288387 bxor 75565881. +-929423147 = -375653665 band -924966411. +-371196929 = -375653665 bor -924966411. +558226218 = -375653665 bxor -924966411. +-2144640911 = -1368431109 band -2118391695. +-1342181893 = -1368431109 bor -2118391695. +802459018 = -1368431109 bxor -2118391695. +1279525509 = 1833199319 band 1289067181. +1842740991 = 1833199319 bor 1289067181. +563215482 = 1833199319 bxor 1289067181. +6164513 = 570333555 band 241054889. +805223931 = 570333555 bor 241054889. +799059418 = 570333555 bxor 241054889. +-1071886267 = -383821361 band -1061391771. +-373326865 = -383821361 bor -1061391771. +698559402 = -383821361 bxor -1061391771. +-2147433503 = -1411267605 band -2079928351. +-1343762453 = -1411267605 bor -2079928351. +803671050 = -1411267605 bxor -2079928351. +1075216645 = 1645654983 band 1228900637. +1799338975 = 1645654983 bor 1228900637. +724122330 = 1645654983 bxor 1228900637. +88113153 = 633390435 band 89168409. +634445691 = 633390435 bor 89168409. +546332538 = 633390435 bxor 89168409. +-1002433387 = -462400321 band -943210795. +-403177729 = -462400321 bor -943210795. +599255658 = -462400321 bxor -943210795. +-2142080687 = -1436582437 band -2125302959. +-1419804709 = -1436582437 bor -2125302959. +722275978 = -1436582437 bxor -2125302959. +1095241861 = 1666063543 band 1174008717. +1744830399 = 1666063543 bor 1174008717. +649588538 = 1666063543 bxor 1174008717. +85788929 = 756927827 band 119487369. +790626267 = 756927827 bor 119487369. +704837338 = 756927827 bxor 119487369. +-1071316219 = -399643729 band -1053358267. +-381685777 = -399643729 bor -1053358267. +689630442 = -399643729 bxor -1053358267. +-2126146879 = -1585998901 band -1991912767. +-1451764789 = -1585998901 bor -1991912767. +674382090 = -1585998901 bxor -1991912767. +1107919269 = 1651089831 band 1176230397. +1719400959 = 1651089831 bor 1176230397. +611481690 = 1651089831 bxor 1176230397. +4161 = 579121475 band 22092025. +601209339 = 579121475 bor 22092025. +601205178 = 579121475 bxor 22092025. +-1006564715 = -424206689 band -872330315. +-289972289 = -424206689 bor -872330315. +716592426 = -424206689 bxor -872330315. +-2109668303 = -1434909253 band -2092437967. +-1417678917 = -1434909253 bor -2092437967. +691989386 = -1434909253 bxor -2092437967. +1076363269 = 1856520855 band 1081883757. +1862041343 = 1856520855 bor 1081883757. +785678074 = 1856520855 bxor 1081883757. +2371617 = 707031347 band 19739241. +724398971 = 707031347 bor 19739241. +722027354 = 707031347 bxor 19739241. +-1073181691 = -399839857 band -1025668059. +-352326225 = -399839857 bor -1025668059. +720855466 = -399839857 bxor -1025668059. +-2139962975 = -1603087445 band -1904228959. +-1367353429 = -1603087445 bor -1904228959. +772609546 = -1603087445 bxor -1904228959. +1157634693 = 1695088519 band 1337072349. +1874526175 = 1695088519 bor 1337072349. +716891482 = 1695088519 bxor 1337072349. +27788545 = 569117987 band 62556121. +603885563 = 569117987 bor 62556121. +576097018 = 569117987 bxor 62556121. +-935311339 = -362260353 band -868038507. +-294987521 = -362260353 bor -868038507. +640323818 = -362260353 bxor -868038507. +-2146412271 = -1607205477 band -2116789999. +-1577583205 = -1607205477 bor -2116789999. +568829066 = -1607205477 bxor -2116789999. +1073762373 = 1615517815 band 1108637005. +1650392447 = 1615517815 bor 1108637005. +576630074 = 1615517815 bxor 1108637005. +25166081 = 562726163 band 96475465. +634035547 = 562726163 bor 96475465. +608869466 = 562726163 bxor 96475465. +-1073217275 = -519151761 band -899153659. +-345088145 = -519151761 bor -899153659. +728129130 = -519151761 bxor -899153659. +-2008514431 = -1471446133 band -1947424639. +-1410356341 = -1471446133 bor -1947424639. +598158090 = -1471446133 bxor -1947424639. +1218988325 = 1760349543 band 1236945853. +1778307071 = 1760349543 bor 1236945853. +559318746 = 1760349543 bxor 1236945853. +38060033 = 711907587 band 63235769. +737083323 = 711907587 bor 63235769. +699023290 = 711907587 bxor 63235769. +-1052508075 = -444857761 band -884722315. +-277072001 = -444857761 bor -884722315. +775436074 = -444857761 bxor -884722315. +-2130173583 = -1459067525 band -2094025743. +-1422919685 = -1459067525 bor -2094025743. +707253898 = -1459067525 bxor -2094025743. +1143512581 = 1697504855 band 1283104301. +1837096575 = 1697504855 bor 1283104301. +693583994 = 1697504855 bxor 1283104301. +34078753 = 667420915 band 168816681. +802158843 = 667420915 bor 168816681. +768080090 = 667420915 bxor 168816681. +-1065336507 = -422559409 band -930191899. +-287414801 = -422559409 bor -930191899. +777921706 = -422559409 bxor -930191899. +-2076171423 = -1535532181 band -2050720927. +-1510081685 = -1535532181 bor -2050720927. +566089738 = -1535532181 bxor -2050720927. +1091307525 = 1762462535 band 1139567773. +1810722783 = 1762462535 bor 1139567773. +719415258 = 1762462535 bxor 1139567773. +75502721 = 780473571 band 78132633. +783103483 = 780473571 bor 78132633. +707600762 = 780473571 bxor 78132633. +-1045950443 = -370533313 band -943877547. +-268460417 = -370533313 bor -943877547. +777490026 = -370533313 bxor -943877547. +-2013250479 = -1368507045 band -1986920751. +-1342177317 = -1368507045 bor -1986920751. +671073162 = -1368507045 bxor -1986920751. +1145050117 = 1716081719 band 1298577165. +1869608767 = 1716081719 bor 1298577165. +724558650 = 1716081719 bxor 1298577165. +223654913 = 760544467 band 257210121. +794099675 = 760544467 bor 257210121. +570444762 = 760544467 bxor 257210121. +-938962427 = -379022545 band -905397563. +-345457681 = -379022545 bor -905397563. +593504746 = -379022545 bxor -905397563. +-1942670783 = -1401605301 band -1942012351. +-1400946869 = -1401605301 bor -1942012351. +541723914 = -1401605301 bxor -1942012351. +1207974181 = 1818343719 band 1241546109. +1851915647 = 1818343719 bor 1241546109. +643941466 = 1818343719 bxor 1241546109. +75776065 = 749125827 band 94139513. +767489275 = 749125827 bor 94139513. +691713210 = 749125827 bxor 94139513. +-1004370411 = -441801185 band -865673419. +-303104193 = -441801185 bor -865673419. +701266218 = -441801185 bxor -865673419. +-2129592015 = -1512209093 band -2093794895. +-1476411973 = -1512209093 bor -2093794895. +653180042 = -1512209093 bxor -2093794895. +1217411589 = 1754610199 band 1318109165. +1855307775 = 1754610199 bor 1318109165. +637896186 = 1754610199 bxor 1318109165. +41967777 = 782852275 band 46558697. +787443195 = 782852275 bor 46558697. +745475418 = 782852275 bxor 46558697. +-997305083 = -456174321 band -946929755. +-405798993 = -456174321 bor -946929755. +591506090 = -456174321 bxor -946929755. +-2087440095 = -1548340437 band -1953173215. +-1414073557 = -1548340437 bor -1953173215. +673366538 = -1548340437 bxor -1953173215. +1101157893 = 1709364999 band 1135509085. +1743716191 = 1709364999 bor 1135509085. +642558298 = 1709364999 bxor 1135509085. +21594113 = 793500835 band 31040345. +802947067 = 793500835 bor 31040345. +781352954 = 793500835 bxor 31040345. +-1028645867 = -491413505 band -805823467. +-268591105 = -491413505 bor -805823467. +760054762 = -491413505 bxor -805823467. +-2142624751 = -1597096677 band -1974770543. +-1429242469 = -1597096677 bor -1974770543. +713382282 = -1597096677 bxor -1974770543. +1157662917 = 1829343223 band 1169209549. +1840889855 = 1829343223 bor 1169209549. +683226938 = 1829343223 bxor 1169209549. +69014657 = 607990931 band 228398281. +767374555 = 607990931 bor 228398281. +698359898 = 607990931 bxor 228398281. +-1059584891 = -520321297 band -975620987. +-436357393 = -520321297 bor -975620987. +623227498 = -520321297 bxor -975620987. +-1984659455 = -1447779573 band -1946315775. +-1409435893 = -1447779573 bor -1946315775. +575223562 = -1447779573 bxor -1946315775. +1149789221 = 1686660327 band 1152282429. +1689153535 = 1686660327 bor 1152282429. +539364314 = 1686660327 bxor 1152282429. +8667137 = 753690755 band 9945657. +754969275 = 753690755 bor 9945657. +746302138 = 753690755 bxor 9945657. +-989787947 = -419231265 band -987150091. +-416593409 = -419231265 bor -987150091. +573194538 = -419231265 bxor -987150091. +-2079300495 = -1397201669 band -2062385295. +-1380286469 = -1397201669 bor -2062385295. +699014026 = -1397201669 bxor -2062385295. diff --git a/erts/emulator/test/big_SUITE_data/eq_big.dat b/erts/emulator/test/big_SUITE_data/eq_big.dat new file mode 100644 index 0000000000..5511d1bf10 --- /dev/null +++ b/erts/emulator/test/big_SUITE_data/eq_big.dat @@ -0,0 +1,13004 @@ +3627225882 = -697 + 3627226579. +-3627227276 = -697 - 3627226579. +-2528176925563 = -697 * 3627226579. +697 = -(-697). +-697 = +(-697). +0 = -697 div 3627226579. +-697 = -697 rem 3627226579. +3627226435 = -697 band 3627226579. +-553 = -697 bor 3627226579. +-3627226988 = -697 bxor 3627226579. +696 = bnot(-697). +-1 = -697 bsl -61. +-1607172577421944684544 = -697 bsr -61. +-283388912239615 = -283388912239613 + -2. +-283388912239611 = -283388912239613 - -2. +566777824479226 = -283388912239613 * -2. +283388912239613 = -(-283388912239613). +-283388912239613 = +(-283388912239613). +141694456119806 = -283388912239613 div -2. +-1 = -283388912239613 rem -2. +-283388912239614 = -283388912239613 band -2. +-1 = -283388912239613 bor -2. +283388912239613 = -283388912239613 bxor -2. +283388912239612 = bnot(-283388912239613). +-104896167137483835127591520601167100453480347078199925156632915223228188306305878154109985624943277357501787279310034030156370067160844817777591157023073455111626047495778039507502639061242015835277440456218702874565483838389693116456108032 = -283388912239613 bsl 746. +-1 = -283388912239613 bsr 746. +899396154689163167548626101 = 899396154689163167641847368 + -93221267. +899396154689163167735068635 = 899396154689163167641847368 - -93221267. +-83842849075051781657306413865575256 = 899396154689163167641847368 * -93221267. +-899396154689163167641847368 = -(899396154689163167641847368). +899396154689163167641847368 = +(899396154689163167641847368). +-9647971794774717743 = 899396154689163167641847368 div -93221267. +72006987 = 899396154689163167641847368 rem -93221267. +899396154689163167574066760 = 899396154689163167641847368 band -93221267. +-25440659 = 899396154689163167641847368 bor -93221267. +-899396154689163167599507419 = 899396154689163167641847368 bxor -93221267. +-899396154689163167641847369 = bnot(899396154689163167641847368). +0 = 899396154689163167641847368 bsl -253. +13017869975433327806566054549187146850478372938959200496342626543873703998010638391600224608668463661056 = 899396154689163167641847368 bsr -253. +38353289727271510973285999751 = 887666814621463939 + 38353289726383844158664535812. +-38353289725496177344043071873 = 887666814621463939 - 38353289726383844158664535812. +34044942521673265192360995015832746373332083468 = 887666814621463939 * 38353289726383844158664535812. +-887666814621463939 = -(887666814621463939). +887666814621463939 = +(887666814621463939). +0 = 887666814621463939 div 38353289726383844158664535812. +887666814621463939 = 887666814621463939 rem 38353289726383844158664535812. +594616166601860352 = 887666814621463939 band 38353289726383844158664535812. +38353289726676894806684139399 = 887666814621463939 bor 38353289726383844158664535812. +38353289726082278640082279047 = 887666814621463939 bxor 38353289726383844158664535812. +-887666814621463940 = bnot(887666814621463939). +0 = 887666814621463939 bsl -787. +722531143980030224978407003366379878572019340627220673638308476197912211331706163856015044590466259639511920085355248108717151013626249732488736624553440916080782402468384420123415848619840265859350798319617560713791523384835232073919483231937051903393792 = 887666814621463939 bsr -787. +-8515461716215666486977884 = -8515461716215666492151278 + 5173394. +-8515461716215666497324672 = -8515461716215666492151278 - 5173394. +-44053838549899831736496468697532 = -8515461716215666492151278 * 5173394. +8515461716215666492151278 = -(-8515461716215666492151278). +-8515461716215666492151278 = +(-8515461716215666492151278). +-1646010668473282045 = -8515461716215666492151278 div 5173394. +-240548 = -8515461716215666492151278 rem 5173394. +417810 = -8515461716215666492151278 band 5173394. +-8515461716215666487395694 = -8515461716215666492151278 bor 5173394. +-8515461716215666487813504 = -8515461716215666492151278 bxor 5173394. +8515461716215666492151277 = bnot(-8515461716215666492151278). +-1 = -8515461716215666492151278 bsl -594. +-552110015119483874455401000114182509753848554122155066504811641532970839680006262116242666380962025577884962904613845097544935294020129261657550847020494270805103895692818062392457706943718836114766692352 = -8515461716215666492151278 bsr -594. +-251589684634846873123391 = -251589684634846873115962 + -7429. +-251589684634846873108533 = -251589684634846873115962 - -7429. +1869059767152277420378481698 = -251589684634846873115962 * -7429. +251589684634846873115962 = -(-251589684634846873115962). +-251589684634846873115962 = +(-251589684634846873115962). +33865888361131629171 = -251589684634846873115962 div -7429. +-4603 = -251589684634846873115962 rem -7429. +-251589684634846873115966 = -251589684634846873115962 band -7429. +-7425 = -251589684634846873115962 bor -7429. +251589684634846873108541 = -251589684634846873115962 bxor -7429. +251589684634846873115961 = bnot(-251589684634846873115962). +-491386102802435299055 = -251589684634846873115962 bsl -9. +-128813918533041599035372544 = -251589684634846873115962 bsr -9. +-871998795379825 = -871998795375248 + -4577. +-871998795370671 = -871998795375248 - -4577. +3991138486432510096 = -871998795375248 * -4577. +871998795375248 = -(-871998795375248). +-871998795375248 = +(-871998795375248). +190517543232 = -871998795375248 div -4577. +-2384 = -871998795375248 rem -4577. +-871998795379696 = -871998795375248 band -4577. +-129 = -871998795375248 bor -4577. +871998795379567 = -871998795375248 bxor -4577. +871998795375247 = bnot(-871998795375248). +-1624225 = -871998795375248 bsl -29. +-468150788536010775986176 = -871998795375248 bsr -29. +-2991637738047072853981278 = -22265889556864555 + -2991637715781183297116723. +2991637693515293740252168 = -22265889556864555 - -2991637715781183297116723. +66611474973734380901960088484083736453265 = -22265889556864555 * -2991637715781183297116723. +22265889556864555 = -(-22265889556864555). +-22265889556864555 = +(-22265889556864555). +0 = -22265889556864555 div -2991637715781183297116723. +-22265889556864555 = -22265889556864555 rem -2991637715781183297116723. +-2991637717189315254902331 = -22265889556864555 band -2991637715781183297116723. +-20857757599078947 = -22265889556864555 bor -2991637715781183297116723. +2991637696331557655823384 = -22265889556864555 bxor -2991637715781183297116723. +22265889556864554 = bnot(-22265889556864555). +-17698916545639237821347114552137310261435038803077739211627488090044459979816479609975948949711590599556505345935296144423539391408146296529089297996491904195783620894238607320078819402991090831482824833109254755662658020392150316325223984043875368960 = -22265889556864555 bsl 777. +-1 = -22265889556864555 bsr 777. +-921330394855903 = -5867913648 + -921324526942255. +921318659028607 = -5867913648 - -921324526942255. +5406252765881601822396240 = -5867913648 * -921324526942255. +5867913648 = -(-5867913648). +-5867913648 = +(-5867913648). +0 = -5867913648 div -921324526942255. +-5867913648 = -5867913648 rem -921324526942255. +-921330042534320 = -5867913648 band -921324526942255. +-352321583 = -5867913648 bor -921324526942255. +921329690212737 = -5867913648 bxor -921324526942255. +5867913647 = bnot(-5867913648). +-10070509970159717552275921442977953280617487172740969541904499886948034952538118239864941771032831232670760838938532099451694651006107378590139473654943040250130202624 = -5867913648 bsl 519. +-1 = -5867913648 bsr 519. +1423045349 = 535282818 + 887762531. +-352479713 = 535282818 - 887762531. +475204029308492358 = 535282818 * 887762531. +-535282818 = -(535282818). +535282818 = +(535282818). +0 = 535282818 div 887762531. +535282818 = 535282818 rem 887762531. +350356482 = 535282818 band 887762531. +1072688867 = 535282818 bor 887762531. +722332385 = 535282818 bxor 887762531. +-535282819 = bnot(535282818). +11595019119157717269464123722338130937385408762397230511002837033772286450351880310576900208963283084603926920717598384092802353509433344 = 535282818 bsl 423. +0 = 535282818 bsr 423. +-9526614229 = -9526614162 + -67. +-9526614095 = -9526614162 - -67. +638283148854 = -9526614162 * -67. +9526614162 = -(-9526614162). +-9526614162 = +(-9526614162). +142188271 = -9526614162 div -67. +-5 = -9526614162 rem -67. +-9526614228 = -9526614162 band -67. +-1 = -9526614162 bor -67. +9526614227 = -9526614162 bxor -67. +9526614161 = bnot(-9526614162). +-4877626450944 = -9526614162 bsl 9. +-18606669 = -9526614162 bsr 9. +-98623731973471913763537026123 = -96141273121197669237423453745 + -2482458852274244526113572378. +-93658814268923424711309881367 = -96141273121197669237423453745 - -2482458852274244526113572378. +238666754528633040727288330786331678776932078104792655610 = -96141273121197669237423453745 * -2482458852274244526113572378. +96141273121197669237423453745 = -(-96141273121197669237423453745). +-96141273121197669237423453745 = +(-96141273121197669237423453745). +38 = -96141273121197669237423453745 div -2482458852274244526113572378. +-1807836734776377245107703381 = -96141273121197669237423453745 rem -2482458852274244526113572378. +-98618669153224018419052574266 = -96141273121197669237423453745 band -2482458852274244526113572378. +-5062820247895344484451857 = -96141273121197669237423453745 bor -2482458852274244526113572378. +98613606332976123074568122409 = -96141273121197669237423453745 bxor -2482458852274244526113572378. +96141273121197669237423453744 = bnot(-96141273121197669237423453745). +-1 = -96141273121197669237423453745 bsl -221. +-323995449482431561430955688380557595865526794242980577682451215826215493438826396507655362314240 = -96141273121197669237423453745 bsr -221. +-96275818948398693347585066750 = -96275818948398693352364564443 + 4779497693. +-96275818948398693357144062136 = -96275818948398693352364564443 - 4779497693. +-460150054555557240921840871850268329999 = -96275818948398693352364564443 * 4779497693. +96275818948398693352364564443 = -(-96275818948398693352364564443). +-96275818948398693352364564443 = +(-96275818948398693352364564443). +-20143501500043237567 = -96275818948398693352364564443 div 4779497693. +-637131512 = -96275818948398693352364564443 rem 4779497693. +4703911941 = -96275818948398693352364564443 band 4779497693. +-96275818948398693352288978691 = -96275818948398693352364564443 bor 4779497693. +-96275818948398693356992890632 = -96275818948398693352364564443 bxor 4779497693. +96275818948398693352364564442 = bnot(-96275818948398693352364564443). +-770206551587189546818916515544 = -96275818948398693352364564443 bsl 3. +-12034477368549836669045570556 = -96275818948398693352364564443 bsr 3. +-272689270240 = -5873 + -272689264367. +272689258494 = -5873 - -272689264367. +1601504049627391 = -5873 * -272689264367. +5873 = -(-5873). +-5873 = +(-5873). +0 = -5873 div -272689264367. +-5873 = -5873 rem -272689264367. +-272689264383 = -5873 band -272689264367. +-5857 = -5873 bor -272689264367. +272689258526 = -5873 bxor -272689264367. +5872 = bnot(-5873). +-1469 = -5873 bsl -2. +-23492 = -5873 bsr -2. +13670759686 = 7826527119 + 5844232567. +1982294552 = 7826527119 - 5844232567. +45740044675368484473 = 7826527119 * 5844232567. +-7826527119 = -(7826527119). +7826527119 = +(7826527119). +1 = 7826527119 div 5844232567. +1982294552 = 7826527119 rem 5844232567. +5642862855 = 7826527119 band 5844232567. +8027896831 = 7826527119 bor 5844232567. +2385033976 = 7826527119 bxor 5844232567. +-7826527120 = bnot(7826527119). +17210715144889395314688 = 7826527119 bsl 41. +0 = 7826527119 bsr 41. +-4341394495791782339893875 = -4341394495791781981452416 + -358441459. +-4341394495791781623010957 = -4341394495791781981452416 - -358441459. +1556135777166175693641714930114944 = -4341394495791781981452416 * -358441459. +4341394495791781981452416 = -(-4341394495791781981452416). +-4341394495791781981452416 = +(-4341394495791781981452416). +12111864815815800 = -4341394495791781981452416 div -358441459. +-354200216 = -4341394495791781981452416 rem -358441459. +-4341394495791782271384064 = -4341394495791781981452416 band -358441459. +-68509811 = -4341394495791781981452416 bor -358441459. +4341394495791782202874253 = -4341394495791781981452416 bxor -358441459. +4341394495791781981452415 = bnot(-4341394495791781981452416). +-32345909593938157 = -4341394495791781981452416 bsl -27. +-582692105576878538621881415630848 = -4341394495791781981452416 bsr -27. +25613348061753413432805 = -62561418842848 + 25613348124314832275653. +-25613348186876251118501 = -62561418842848 - 25613348124314832275653. +-1602407399972935425479526309823579744 = -62561418842848 * 25613348124314832275653. +62561418842848 = -(-62561418842848). +-62561418842848 = +(-62561418842848). +0 = -62561418842848 div 25613348124314832275653. +-62561418842848 = -62561418842848 rem 25613348124314832275653. +25613348062046077323264 = -62561418842848 band 25613348124314832275653. +-292663890459 = -62561418842848 bor 25613348124314832275653. +-25613348062338741213723 = -62561418842848 bxor 25613348124314832275653. +62561418842847 = bnot(-62561418842848). +-619578282400515063188185698798133487599616 = -62561418842848 bsl 93. +-1 = -62561418842848 bsr 93. +-415145595976523548470677 = -21466329235395744132 + -415124129647288152726545. +415102663318052756982413 = -21466329235395744132 - -415124129647288152726545. +8911191240565794849702499410197724984383940 = -21466329235395744132 * -415124129647288152726545. +21466329235395744132 = -(-21466329235395744132). +-21466329235395744132 = +(-21466329235395744132). +0 = -21466329235395744132 div -415124129647288152726545. +-21466329235395744132 = -21466329235395744132 rem -415124129647288152726545. +-415124229342963475389844 = -21466329235395744132 band -415124129647288152726545. +-21366633560073080833 = -21466329235395744132 bor -415124129647288152726545. +415102862709403402309011 = -21466329235395744132 bxor -415124129647288152726545. +21466329235395744131 = bnot(-21466329235395744132). +-10990760568522620995584 = -21466329235395744132 bsl 9. +-41926424287882313 = -21466329235395744132 bsr 9. +76468874711569513325056778 = 76468874711569513317743546 + 7313232. +76468874711569513310430314 = 76468874711569513317743546 - 7313232. +559234621544640935019748268400672 = 76468874711569513317743546 * 7313232. +-76468874711569513317743546 = -(76468874711569513317743546). +76468874711569513317743546 = +(76468874711569513317743546). +10456235315872587293 = 76468874711569513317743546 div 7313232. +3782570 = 76468874711569513317743546 rem 7313232. +2429712 = 76468874711569513317743546 band 7313232. +76468874711569513322627066 = 76468874711569513317743546 bor 7313232. +76468874711569513320197354 = 76468874711569513317743546 bxor 7313232. +-76468874711569513317743547 = bnot(76468874711569513317743546). +0 = 76468874711569513317743546 bsl -746. +28304889556786495453831814324215420256373810154437575218925605423140242106417314289689964336921067023412402676980609685783148483385245613331457090830852471386788403077786640815058022739945601734382573174324776692555808679848887824494250404725122924544 = 76468874711569513317743546 bsr -746. +-5897699569812678369906 = -762 + -5897699569812678369144. +5897699569812678368382 = -762 - -5897699569812678369144. +4494047072197260917287728 = -762 * -5897699569812678369144. +762 = -(-762). +-762 = +(-762). +0 = -762 div -5897699569812678369144. +-762 = -762 rem -5897699569812678369144. +-5897699569812678369280 = -762 band -5897699569812678369144. +-626 = -762 bor -5897699569812678369144. +5897699569812678368654 = -762 bxor -5897699569812678369144. +761 = bnot(-762). +-1 = -762 bsl -47. +-107241966126759936 = -762 bsr -47. +93648805036749 = 93648894616213 + -89579464. +93648984195677 = 93648894616213 - -89579464. +-8389017783912846249832 = 93648894616213 * -89579464. +-93648894616213 = -(93648894616213). +93648894616213 = +(93648894616213). +-1045428 = 93648894616213 div -89579464. +14725621 = 93648894616213 rem -89579464. +93648809631760 = 93648894616213 band -89579464. +-4595011 = 93648894616213 bor -89579464. +-93648814226771 = 93648894616213 bxor -89579464. +-93648894616214 = bnot(93648894616213). +50277367460398163296256 = 93648894616213 bsl 29. +174434 = 93648894616213 bsr 29. +-5348788016 = -5287491547 + -61296469. +-5226195078 = -5287491547 - -61296469. +324104561698447543 = -5287491547 * -61296469. +5287491547 = -(-5287491547). +-5287491547 = +(-5287491547). +86 = -5287491547 div -61296469. +-15995213 = -5287491547 rem -61296469. +-5296357343 = -5287491547 band -61296469. +-52430673 = -5287491547 bor -61296469. +5243926670 = -5287491547 bxor -61296469. +5287491546 = bnot(-5287491547). +-1 = -5287491547 bsl -85. +-204549921669196753881551737878216704 = -5287491547 bsr -85. +762439979239339795156546850 = 762439979239339795156537669 + 9181. +762439979239339795156528488 = 762439979239339795156537669 - 9181. +6999961449396378659332172339089 = 762439979239339795156537669 * 9181. +-762439979239339795156537669 = -(762439979239339795156537669). +762439979239339795156537669 = +(762439979239339795156537669). +83045417627637489941894 = 762439979239339795156537669 div 9181. +8855 = 762439979239339795156537669 rem 9181. +325 = 762439979239339795156537669 band 9181. +762439979239339795156546525 = 762439979239339795156537669 bor 9181. +762439979239339795156546200 = 762439979239339795156537669 bxor 9181. +-762439979239339795156537670 = bnot(762439979239339795156537669). +45201673274459720178644042862458985496925598168922005361232603694334612864372839655498293719782600063582208 = 762439979239339795156537669 bsl 265. +0 = 762439979239339795156537669 bsr 265. +-556183529548738362375165 = -556183529548742715698331 + 4353323166. +-556183529548747069021497 = -556183529548742715698331 - 4353323166. +-2421246643732187190423296209835946 = -556183529548742715698331 * 4353323166. +556183529548742715698331 = -(-556183529548742715698331). +-556183529548742715698331 = +(-556183529548742715698331). +-127760680367725 = -556183529548742715698331 div 4353323166. +-4074480981 = -556183529548742715698331 rem 4353323166. +4348448772 = -556183529548742715698331 band 4353323166. +-556183529548742710823937 = -556183529548742715698331 bor 4353323166. +-556183529548747059272709 = -556183529548742715698331 bxor 4353323166. +556183529548742715698330 = bnot(-556183529548742715698331). +-164156403641570095641504089198946277272846336 = -556183529548742715698331 bsl 68. +-1885 = -556183529548742715698331 bsr 68. +-58828870360392725 = -58828872875851219 + 2515458494. +-58828875391309713 = -58828872875851219 - 2515458494. +-147981587968006156313804186 = -58828872875851219 * 2515458494. +58828872875851219 = -(-58828872875851219). +-58828872875851219 = +(-58828872875851219). +-23386938 = -58828872875851219 div 2515458494. +-1035099847 = -58828872875851219 rem 2515458494. +2174926892 = -58828872875851219 band 2515458494. +-58828872535319617 = -58828872875851219 bor 2515458494. +-58828874710246509 = -58828872875851219 bxor 2515458494. +58828872875851218 = bnot(-58828872875851219). +-1 = -58828872875851219 bsl -897. +-62157943626374948997432249001986780504201035968394074770676882720538609168733361134066329678956567940750449072796753898138503322952919077398530702139123003614916021436073293455615861224266659917484107541556523561584386197396750779974331385916265028971325138931043761240917394354411143168 = -58828872875851219 bsr -897. +958617833851552 = 959151593526117 + -533759674565. +959685353200682 = 959151593526117 - -533759674565. +-511956442419001370748114105 = 959151593526117 * -533759674565. +-959151593526117 = -(959151593526117). +959151593526117 = +(959151593526117). +-1796 = 959151593526117 div -533759674565. +519218007377 = 959151593526117 rem -533759674565. +958789708714785 = 959151593526117 band -533759674565. +-171874863233 = 959151593526117 bor -533759674565. +-958961583578018 = 959151593526117 bxor -533759674565. +-959151593526118 = bnot(959151593526117). +0 = 959151593526117 bsl -396. +154798067840604982832706767635620816692372607293762470743157215497890321537138188100605114026166068788312392515811048749195833808781312 = 959151593526117 bsr -396. +-24447692715287 = 2228231 + -24447694943518. +24447697171749 = 2228231 - -24447694943518. +-54475111751690056658 = 2228231 * -24447694943518. +-2228231 = -(2228231). +2228231 = +(2228231). +0 = 2228231 div -24447694943518. +2228231 = 2228231 rem -24447694943518. +131074 = 2228231 band -24447694943518. +-24447692846361 = 2228231 bor -24447694943518. +-24447692977435 = 2228231 bxor -24447694943518. +-2228232 = bnot(2228231). +1412309182298573913763200240009084928 = 2228231 bsl 99. +0 = 2228231 bsr 99. +-529636755821667055158 = -93556888355645 + -529636662264778699513. +529636568707890343868 = -93556888355645 - -529636662264778699513. +49551158080562357886280616132300885 = -93556888355645 * -529636662264778699513. +93556888355645 = -(-93556888355645). +-93556888355645 = +(-93556888355645). +0 = -93556888355645 div -529636662264778699513. +-93556888355645 = -93556888355645 rem -529636662264778699513. +-529636685380830622717 = -93556888355645 band -529636662264778699513. +-70440836432441 = -93556888355645 bor -529636662264778699513. +529636614939994190276 = -93556888355645 bxor -529636662264778699513. +93556888355644 = bnot(-93556888355645). +-365456595140 = -93556888355645 bsl -8. +-23950563419045120 = -93556888355645 bsr -8. +92142373454895610795790155642 = 92142373447271694876236992324 + 7623915919553163318. +92142373439647778956683829006 = 92142373447271694876236992324 - 7623915919553163318. +702485707790067362709541849380847259784284371032 = 92142373447271694876236992324 * 7623915919553163318. +-92142373447271694876236992324 = -(92142373447271694876236992324). +92142373447271694876236992324 = +(92142373447271694876236992324). +12085964013 = 92142373447271694876236992324 div 7623915919553163318. +5414359974577317190 = 92142373447271694876236992324 rem 7623915919553163318. +7602101606705807364 = 92142373447271694876236992324 band 7623915919553163318. +92142373447293509189084348278 = 92142373447271694876236992324 bor 7623915919553163318. +92142373439691407582378540914 = 92142373447271694876236992324 bxor 7623915919553163318. +-92142373447271694876236992325 = bnot(92142373447271694876236992324). +23588447602501553888316670034944 = 92142373447271694876236992324 bsl 8. +359931146278405058110300751 = 92142373447271694876236992324 bsr 8. +-55748392941580801751 = 514177926246 + -55748393455758727997. +55748393969936654243 = 514177926246 - -55748393455758727997. +-28664593338628100308012241309262 = 514177926246 * -55748393455758727997. +-514177926246 = -(514177926246). +514177926246 = +(514177926246). +0 = 514177926246 div -55748393455758727997. +514177926246 = 514177926246 rem -55748393455758727997. +21579695170 = 514177926246 band -55748393455758727997. +-55748392963160496921 = 514177926246 bor -55748393455758727997. +-55748392984740192091 = 514177926246 bxor -55748393455758727997. +-514177926247 = bnot(514177926246). +131629549118976 = 514177926246 bsl 8. +2008507524 = 514177926246 bsr 8. +6972198921324448981856466 = 474612 + 6972198921324448981381854. +-6972198921324448980907242 = 474612 - 6972198921324448981381854. +3309089274447639379951604490648 = 474612 * 6972198921324448981381854. +-474612 = -(474612). +474612 = +(474612). +0 = 474612 div 6972198921324448981381854. +474612 = 474612 rem 6972198921324448981381854. +143572 = 474612 band 6972198921324448981381854. +6972198921324448981712894 = 474612 bor 6972198921324448981381854. +6972198921324448981569322 = 474612 bxor 6972198921324448981381854. +-474613 = bnot(474612). +1853 = 474612 bsl -8. +121500672 = 474612 bsr -8. +-62665821848439446596209498285 = -62665821855634398988562936143 + 7194952392353437858. +-62665821862829351380916374001 = -62665821855634398988562936143 - 7194952392353437858. +-450877604878991071526708285254256154704572701694 = -62665821855634398988562936143 * 7194952392353437858. +62665821855634398988562936143 = -(-62665821855634398988562936143). +-62665821855634398988562936143 = +(-62665821855634398988562936143). +-8709692356 = -62665821855634398988562936143 div 7194952392353437858. +-2169748426419322695 = -62665821855634398988562936143 rem 7194952392353437858. +2382407589730371744 = -62665821855634398988562936143 band 7194952392353437858. +-62665821850821854185939870029 = -62665821855634398988562936143 bor 7194952392353437858. +-62665821853204261775670241773 = -62665821855634398988562936143 bxor 7194952392353437858. +62665821855634398988562936142 = bnot(-62665821855634398988562936143). +-1084817767643660244780522213629153953898926080345040453069544371713234463275536771280298267170010833880597802476198435796829522365121191004077579629400494449329542774627983279936815553926960929899067484269699889551711727747590392357842956761256251073907540863242281989377617906220851861591680884999716864 = -62665821855634398988562936143 bsl 911. +-1 = -62665821855634398988562936143 bsr 911. +94260648081969 = 98519912838757 + -4259264756788. +102779177595545 = 98519912838757 - -4259264756788. +-419622392595943292265232516 = 98519912838757 * -4259264756788. +-98519912838757 = -(98519912838757). +98519912838757 = +(98519912838757). +-23 = 98519912838757 div -4259264756788. +556823432633 = 98519912838757 rem -4259264756788. +96758365946436 = 98519912838757 band -4259264756788. +-2497717864467 = 98519912838757 bor -4259264756788. +-99256083810903 = 98519912838757 bxor -4259264756788. +-98519912838758 = bnot(98519912838757). +1377686678635590569341335761341476992469445833833739901863031756572672973825711307939900985089843549770640275075499187023317754094386723724653949486126864958044191347876801655313662239288766310820240641344937421666103930076472730808791105944640660351508298072064 = 98519912838757 bsl 821. +0 = 98519912838757 bsr 821. +-484369358674959980331422569 = -85182295312 + -484369358674959895149127257. +484369358674959809966831945 = -85182295312 - -484369358674959895149127257. +41259693750734482808349514284842519184 = -85182295312 * -484369358674959895149127257. +85182295312 = -(-85182295312). +-85182295312 = +(-85182295312). +0 = -85182295312 div -484369358674959895149127257. +-85182295312 = -85182295312 rem -484369358674959895149127257. +-484369358674959975763652448 = -85182295312 band -484369358674959895149127257. +-4567770121 = -85182295312 bor -484369358674959895149127257. +484369358674959971195882327 = -85182295312 bxor -484369358674959895149127257. +85182295311 = bnot(-85182295312). +-658380353059922195180871506894252321738235694807762272644705873309199760459060567795020296114869851753437837983701591902586517465082146648836526078746238102492112557942174580605976576 = -85182295312 bsl 571. +-1 = -85182295312 bsr 571. +-2694483758798 = -8325666717994 + 5631182959196. +-13956849677190 = -8325666717994 - 5631182959196. +-46883352546313102140972824 = -8325666717994 * 5631182959196. +8325666717994 = -(-8325666717994). +-8325666717994 = +(-8325666717994). +-1 = -8325666717994 div 5631182959196. +-2694483758798 = -8325666717994 rem 5631182959196. +55910117972 = -8325666717994 band 5631182959196. +-2750393876770 = -8325666717994 bor 5631182959196. +-2806303994742 = -8325666717994 bxor 5631182959196. +8325666717993 = bnot(-8325666717994). +-33302666871976 = -8325666717994 bsl 2. +-2081416679499 = -8325666717994 bsr 2. +19250113 = 24817572 + -5567459. +30385031 = 24817572 - -5567459. +-138170814589548 = 24817572 * -5567459. +-24817572 = -(24817572). +24817572 = +(24817572). +-4 = 24817572 div -5567459. +2547736 = 24817572 rem -5567459. +19532804 = 24817572 band -5567459. +-282691 = 24817572 bor -5567459. +-19815495 = 24817572 bxor -5567459. +-24817573 = bnot(24817572). +3176649216 = 24817572 bsl 7. +193887 = 24817572 bsr 7. +-986197265 = -986197241 + -24. +-986197217 = -986197241 - -24. +23668733784 = -986197241 * -24. +986197241 = -(-986197241). +-986197241 = +(-986197241). +41091551 = -986197241 div -24. +-17 = -986197241 rem -24. +-986197248 = -986197241 band -24. +-17 = -986197241 bor -24. +986197231 = -986197241 bxor -24. +986197240 = bnot(-986197241). +-1 = -986197241 bsl -81. +-2384478615755221950666675513720832 = -986197241 bsr -81. +732942200343775581690880232 = 732934871577251234126124376 + 7328766524347564755856. +732927542810726886561368520 = 732934871577251234126124376 - 7328766524347564755856. +5371508551342340254299322759521810138255930345856 = 732934871577251234126124376 * 7328766524347564755856. +-732934871577251234126124376 = -(732934871577251234126124376). +732934871577251234126124376 = +(732934871577251234126124376). +100007 = 732934871577251234126124376 div 7328766524347564755856. +6917776824325587233384 = 732934871577251234126124376 rem 7328766524347564755856. +2600995417994822156560 = 732934871577251234126124376 band 7328766524347564755856. +732939599348357586868723672 = 732934871577251234126124376 bor 7328766524347564755856. +732936998352939592046567112 = 732934871577251234126124376 bxor 7328766524347564755856. +-732934871577251234126124377 = bnot(732934871577251234126124376). +55082520201569452267604508957951350510286308219191612295828187656546553125849458644923371557579438629117140030970114012095759709458399232 = 732934871577251234126124376 bsl 365. +0 = 732934871577251234126124376 bsr 365. +546282386 = 546282474 + -88. +546282562 = 546282474 - -88. +-48072857712 = 546282474 * -88. +-546282474 = -(546282474). +546282474 = +(546282474). +-6207755 = 546282474 div -88. +34 = 546282474 rem -88. +546282408 = 546282474 band -88. +-22 = 546282474 bor -88. +-546282430 = 546282474 bxor -88. +-546282475 = bnot(546282474). +0 = 546282474 bsl -813. +29840338297334282138450456656187711109660907212364379909472719157266715168793742613319458215652373579139998102057611417555902445129790415236383563474617625018813617946269840102762316133855929231416002055980335539109980770638424358837471127735450896171008 = 546282474 bsr -813. +4322312878927677411598763 = 4322312878917964499415617 + 9712912183146. +4322312878908251587232471 = 4322312878917964499415617 - 9712912183146. +41982245421011158924257465556676591082 = 4322312878917964499415617 * 9712912183146. +-4322312878917964499415617 = -(4322312878917964499415617). +4322312878917964499415617 = +(4322312878917964499415617). +445006893650 = 4322312878917964499415617 div 9712912183146. +923154992717 = 4322312878917964499415617 rem 9712912183146. +9643921384000 = 4322312878917964499415617 band 9712912183146. +4322312878918033490214763 = 4322312878917964499415617 bor 9712912183146. +4322312878908389568830763 = 4322312878917964499415617 bxor 9712912183146. +-4322312878917964499415618 = bnot(4322312878917964499415617). +31859856237028551888120820009923328758300029661585733548532377883593603909573437430715960643388604457851166218950251358566044377514463637163386275663830923200450335964662085432581827661398016 = 4322312878917964499415617 bsl 551. +0 = 4322312878917964499415617 bsr 551. +-337755121673376495033 = 511116728 + -337755121673887611761. +337755121674398728489 = 511116728 - -337755121673887611761. +-172632292655199319163016638008 = 511116728 * -337755121673887611761. +-511116728 = -(511116728). +511116728 = +(511116728). +0 = 511116728 div -337755121673887611761. +511116728 = 511116728 rem -337755121673887611761. +102171784 = 511116728 band -337755121673887611761. +-337755121673478666817 = 511116728 bor -337755121673887611761. +-337755121673580838601 = 511116728 bxor -337755121673887611761. +-511116729 = bnot(511116728). +127779182 = 511116728 bsl -2. +2044466912 = 511116728 bsr -2. +-6656675232558356241402161741 = -6656675232558356263876529115 + 22474367374. +-6656675232558356286350896489 = -6656675232558356263876529115 - 22474367374. +-149604564665923384567935200706517094010 = -6656675232558356263876529115 * 22474367374. +6656675232558356263876529115 = -(-6656675232558356263876529115). +-6656675232558356263876529115 = +(-6656675232558356263876529115). +-296189660059543541 = -6656675232558356263876529115 div 22474367374. +-8693697781 = -6656675232558356263876529115 rem 22474367374. +5284962308 = -6656675232558356263876529115 band 22474367374. +-6656675232558356246687124049 = -6656675232558356263876529115 bor 22474367374. +-6656675232558356251972086357 = -6656675232558356263876529115 bxor 22474367374. +6656675232558356263876529114 = bnot(-6656675232558356263876529115). +-4098224355635156475671491056479847988400246161035515855685751443750385849166363304055370075768214282026921745868015574871345586307288593858560 = -6656675232558356263876529115 bsl 378. +-1 = -6656675232558356263876529115 bsr 378. +-834784265375442923 = 492876415643 + -834784758251858566. +834785251128274209 = 492876415643 - -834784758251858566. +-411445719480584316653065947938 = 492876415643 * -834784758251858566. +-492876415643 = -(492876415643). +492876415643 = +(492876415643). +0 = 492876415643 div -834784758251858566. +492876415643 = 492876415643 rem -834784758251858566. +147106316314 = 492876415643 band -834784758251858566. +-834784412481759237 = 492876415643 bor -834784758251858566. +-834784559588075551 = 492876415643 bxor -834784758251858566. +-492876415644 = bnot(492876415643). +7886022650288 = 492876415643 bsl 4. +30804775977 = 492876415643 bsr 4. +786997892440 = 786994155228 + 3737212. +786990418016 = 786994155228 - 3737212. +2941164000847944336 = 786994155228 * 3737212. +-786994155228 = -(786994155228). +786994155228 = +(786994155228). +210583 = 786994155228 div 3737212. +840632 = 786994155228 rem 3737212. +67164 = 786994155228 band 3737212. +786997825276 = 786994155228 bor 3737212. +786997758112 = 786994155228 bxor 3737212. +-786994155229 = bnot(786994155228). +5561993252649343873980481383423107439067560947225604842146139928323085688976506355712 = 786994155228 bsl 242. +0 = 786994155228 bsr 242. +4598250297565 = -9548772 + 4598259846337. +-4598269395109 = -9548772 - 4598259846337. +-43907734869427048164 = -9548772 * 4598259846337. +9548772 = -(-9548772). +-9548772 = +(-9548772). +0 = -9548772 div 4598259846337. +-9548772 = -9548772 rem 4598259846337. +4598251392000 = -9548772 band 4598259846337. +-1094435 = -9548772 bor 4598259846337. +-4598252486435 = -9548772 bxor 4598259846337. +9548771 = bnot(-9548772). +-1 = -9548772 bsl -27. +-1281614483030016 = -9548772 bsr -27. +17 = -77 + 94. +-171 = -77 - 94. +-7238 = -77 * 94. +77 = -(-77). +-77 = +(-77). +0 = -77 div 94. +-77 = -77 rem 94. +18 = -77 band 94. +-1 = -77 bor 94. +-19 = -77 bxor 94. +76 = bnot(-77). +-3 = -77 bsl -5. +-2464 = -77 bsr -5. +77134258283273549 = -6 + 77134258283273555. +-77134258283273561 = -6 - 77134258283273555. +-462805549699641330 = -6 * 77134258283273555. +6 = -(-6). +-6 = +(-6). +0 = -6 div 77134258283273555. +-6 = -6 rem 77134258283273555. +77134258283273554 = -6 band 77134258283273555. +-5 = -6 bor 77134258283273555. +-77134258283273559 = -6 bxor 77134258283273555. +5 = bnot(-6). +-384 = -6 bsl 6. +-1 = -6 bsr 6. +29183275531772892507 = -55766289 + 29183275531828658796. +-29183275531884425085 = -55766289 - 29183275531828658796. +-1627442977274585684900128044 = -55766289 * 29183275531828658796. +55766289 = -(-55766289). +-55766289 = +(-55766289). +0 = -55766289 div 29183275531828658796. +-55766289 = -55766289 rem 29183275531828658796. +29183275531823284844 = -55766289 band 29183275531828658796. +-50392337 = -55766289 bor 29183275531828658796. +-29183275531873677181 = -55766289 bxor 29183275531828658796. +55766288 = bnot(-55766289). +-4018384613763766240149504 = -55766289 bsl 56. +-1 = -55766289 bsr 56. +365086117139147091661 = 361132233426153168792 + 3953883712993922869. +357178349713159245923 = 361132233426153168792 - 3953883712993922869. +1427874855980786554439175373063185904248 = 361132233426153168792 * 3953883712993922869. +-361132233426153168792 = -(361132233426153168792). +361132233426153168792 = +(361132233426153168792). +91 = 361132233426153168792 div 3953883712993922869. +1328815543706187713 = 361132233426153168792 rem 3953883712993922869. +1339544090379063056 = 361132233426153168792 band 3953883712993922869. +363746573048768028605 = 361132233426153168792 bor 3953883712993922869. +362407028958388965549 = 361132233426153168792 bxor 3953883712993922869. +-361132233426153168793 = bnot(361132233426153168792). +0 = 361132233426153168792 bsl -696. +118725289140703491556836465932452495756105260575954009599581403128900049342467809199936615485148280430682318251152714265033690995374449129825872565827751619376374351380769605395391077677220595122612287408817961317361349732033626112 = 361132233426153168792 bsr -696. +-6141584268641914214120 = -6141584268641914217341 + 3221. +-6141584268641914220562 = -6141584268641914217341 - 3221. +-19782042929295605694055361 = -6141584268641914217341 * 3221. +6141584268641914217341 = -(-6141584268641914217341). +-6141584268641914217341 = +(-6141584268641914217341). +-1906732154188734621 = -6141584268641914217341 div 3221. +-3100 = -6141584268641914217341 rem 3221. +3201 = -6141584268641914217341 band 3221. +-6141584268641914217321 = -6141584268641914217341 bor 3221. +-6141584268641914220522 = -6141584268641914217341 bxor 3221. +6141584268641914217340 = bnot(-6141584268641914217341). +-1751288345237585826291073747928848023048343983742588022682591874328785777092434928905126541446820557558701485007668624934352026410694513865411795125375468600332166887490883186250928441914174496707171387583523454976 = -6141584268641914217341 bsl 636. +-1 = -6141584268641914217341 bsr 636. +67861760423550 = 61265567725173 + 6596192698377. +54669375026796 = 61265567725173 - 6596192698377. +404119490490707732419144221 = 61265567725173 * 6596192698377. +-61265567725173 = -(61265567725173). +61265567725173 = +(61265567725173). +9 = 61265567725173 div 6596192698377. +1899833439780 = 61265567725173 rem 6596192698377. +6289981702145 = 61265567725173 band 6596192698377. +61571778721405 = 61265567725173 bor 6596192698377. +55281797019260 = 61265567725173 bxor 6596192698377. +-61265567725174 = bnot(61265567725173). +239318623926 = 61265567725173 bsl -8. +15683985337644288 = 61265567725173 bsr -8. +47116745348335290 = -8 + 47116745348335298. +-47116745348335306 = -8 - 47116745348335298. +-376933962786682384 = -8 * 47116745348335298. +8 = -(-8). +-8 = +(-8). +0 = -8 div 47116745348335298. +-8 = -8 rem 47116745348335298. +47116745348335296 = -8 band 47116745348335298. +-6 = -8 bor 47116745348335298. +-47116745348335302 = -8 bxor 47116745348335298. +7 = bnot(-8). +-32 = -8 bsl 2. +-2 = -8 bsr 2. +-88573984901610957 = -88567592543696663 + -6392357914294. +-88561200185782369 = -88567592543696663 - -6392357914294. +566155751146665626751287800922 = -88567592543696663 * -6392357914294. +88567592543696663 = -(-88567592543696663). +-88567592543696663 = +(-88567592543696663). +13855 = -88567592543696663 div -6392357914294. +-1473641153293 = -88567592543696663 rem -6392357914294. +-88567662371518392 = -88567592543696663 band -6392357914294. +-6322530092565 = -88567592543696663 bor -6392357914294. +88561339841425827 = -88567592543696663 bxor -6392357914294. +88567592543696662 = bnot(-88567592543696663). +-45346607382372691456 = -88567592543696663 bsl 9. +-172983579186908 = -88567592543696663 bsr 9. +-9146156523089801569030876897 = -8817572254811883426431653785 + -328584268277918142599223112. +-8488987986533965283832430673 = -8817572254811883426431653785 - -328584268277918142599223112. +2897315527335035496667139099181367051282066106354278920 = -8817572254811883426431653785 * -328584268277918142599223112. +8817572254811883426431653785 = -(-8817572254811883426431653785). +-8817572254811883426431653785 = +(-8817572254811883426431653785). +26 = -8817572254811883426431653785 div -328584268277918142599223112. +-274381279586011718851852873 = -8817572254811883426431653785 rem -328584268277918142599223112. +-9129798012702552983602681824 = -8817572254811883426431653785 band -328584268277918142599223112. +-16358510387248585428195073 = -8817572254811883426431653785 bor -328584268277918142599223112. +9113439502315304398174486751 = -8817572254811883426431653785 bxor -328584268277918142599223112. +8817572254811883426431653784 = bnot(-8817572254811883426431653785). +-2204393063702970856607913447 = -8817572254811883426431653785 bsl -2. +-35270289019247533705726615140 = -8817572254811883426431653785 bsr -2. +465928375553828382292956748 = -3346318897841 + 465928375553831728611854589. +-465928375553835074930752430 = -3346318897841 - 465928375553831728611854589. +-1559144928156145718052797073149438042349 = -3346318897841 * 465928375553831728611854589. +3346318897841 = -(-3346318897841). +-3346318897841 = +(-3346318897841). +0 = -3346318897841 div 465928375553831728611854589. +-3346318897841 = -3346318897841 rem 465928375553831728611854589. +465928375553830594738128973 = -3346318897841 band 465928375553831728611854589. +-2212445172225 = -3346318897841 bor 465928375553831728611854589. +-465928375553832807183301198 = -3346318897841 bxor 465928375553831728611854589. +3346318897840 = bnot(-3346318897841). +-1 = -3346318897841 bsl -73. +-31605088408315261556739799276060672 = -3346318897841 bsr -73. +-62714104103016144602 = 21419246681141769 + -62735523349697286371. +62756942596378428140 = 21419246681141769 - -62735523349697286371. +-1343747650297695555866511519242530299 = 21419246681141769 * -62735523349697286371. +-21419246681141769 = -(21419246681141769). +21419246681141769 = +(21419246681141769). +0 = 21419246681141769 div -62735523349697286371. +21419246681141769 = 21419246681141769 rem -62735523349697286371. +21392787656221193 = 21419246681141769 band -62735523349697286371. +-62735496890672365795 = 21419246681141769 bor -62735523349697286371. +-62756889678328586988 = 21419246681141769 bxor -62735523349697286371. +-21419246681141770 = bnot(21419246681141769). +301135451132850879823076333720532272357865951171292782157020618613801305055882637248865896221318709819446722148208834930598535508005104228433238569815922886879036217445134106624 = 21419246681141769 bsl 532. +0 = 21419246681141769 bsr 532. +-422346012809773866 = 287563561651815 + -422633576371425681. +422921139933077496 = 287563561651815 - -422633576371425681. +-121534016495011532057750871261015 = 287563561651815 * -422633576371425681. +-287563561651815 = -(287563561651815). +287563561651815 = +(287563561651815). +0 = 287563561651815 div -422633576371425681. +287563561651815 = 287563561651815 rem -422633576371425681. +1099548348007 = 287563561651815 band -422633576371425681. +-422347112358121873 = 287563561651815 bor -422633576371425681. +-422348211906469880 = 287563561651815 bxor -422633576371425681. +-287563561651816 = bnot(287563561651815). +0 = 287563561651815 bsl -69. +169747565654893748186088190802657280 = 287563561651815 bsr -69. +5798686886864655553 = 5798686886864655561 + -8. +5798686886864655569 = 5798686886864655561 - -8. +-46389495094917244488 = 5798686886864655561 * -8. +-5798686886864655561 = -(5798686886864655561). +5798686886864655561 = +(5798686886864655561). +-724835860858081945 = 5798686886864655561 div -8. +1 = 5798686886864655561 rem -8. +5798686886864655560 = 5798686886864655561 band -8. +-7 = 5798686886864655561 bor -8. +-5798686886864655567 = 5798686886864655561 bxor -8. +-5798686886864655562 = bnot(5798686886864655561). +2765029376442 = 5798686886864655561 bsl -21. +12160727802161986139062272 = 5798686886864655561 bsr -21. +34535239279974682 = 34535239283838143 + -3863461. +34535239287701604 = 34535239283838143 - -3863461. +-133425550098776595792923 = 34535239283838143 * -3863461. +-34535239283838143 = -(34535239283838143). +34535239283838143 = +(34535239283838143). +-8938938243 = 34535239283838143 div -3863461. +599120 = 34535239283838143 rem -3863461. +34535239280036891 = 34535239283838143 band -3863461. +-62209 = 34535239283838143 bor -3863461. +-34535239280099100 = 34535239283838143 bxor -3863461. +-34535239283838144 = bnot(34535239283838143). +4635241352613102673199104 = 34535239283838143 bsl 27. +257307583 = 34535239283838143 bsr 27. +-368153716082640201944396754031 = 76753291427389858788 + -368153716159393493371786612819. +368153716236146784799176471607 = 76753291427389858788 - -368153716159393493371786612819. +-28257009466458495941911927915494931764981240603372 = 76753291427389858788 * -368153716159393493371786612819. +-76753291427389858788 = -(76753291427389858788). +76753291427389858788 = +(76753291427389858788). +0 = 76753291427389858788 div -368153716159393493371786612819. +76753291427389858788 = 76753291427389858788 rem -368153716159393493371786612819. +72118344229069732 = 76753291427389858788 band -368153716159393493371786612819. +-368153716082712320288625823763 = 76753291427389858788 bor -368153716159393493371786612819. +-368153716082784438632854893495 = 76753291427389858788 bxor -368153716159393493371786612819. +-76753291427389858789 = bnot(76753291427389858788). +0 = 76753291427389858788 bsl -366. +11536535890257593071038976300375871109868892628109738378273396023014903115688063580778111060947038640339585509431463222210442821632 = 76753291427389858788 bsr -366. +1884609829208532322882303799 = 2248556246542721798153863135 + -363946417334189475271559336. +2612502663876911273425422471 = 2248556246542721798153863135 - -363946417334189475271559336. +-818353990103636068016594906757526612446893223775478360 = 2248556246542721798153863135 * -363946417334189475271559336. +-2248556246542721798153863135 = -(2248556246542721798153863135). +2248556246542721798153863135 = +(2248556246542721798153863135). +-6 = 2248556246542721798153863135 div -363946417334189475271559336. +64877742537584946524507119 = 2248556246542721798153863135 rem -363946417334189475271559336. +1937843304908427225687799640 = 2248556246542721798153863135 band -363946417334189475271559336. +-53233475699894902805495841 = 2248556246542721798153863135 bor -363946417334189475271559336. +-1991076780608322128493295481 = 2248556246542721798153863135 bxor -363946417334189475271559336. +-2248556246542721798153863136 = bnot(2248556246542721798153863135). +7801246615 = 2248556246542721798153863135 bsl -58. +648102212739289793590374371758327316548157440 = 2248556246542721798153863135 bsr -58. +-927242187530948173 = 881216 + -927242187531829389. +927242187532710605 = 881216 - -927242187531829389. +-817100651528048566857024 = 881216 * -927242187531829389. +-881216 = -(881216). +881216 = +(881216). +0 = 881216 div -927242187531829389. +881216 = 881216 rem -927242187531829389. +537152 = 881216 band -927242187531829389. +-927242187531485325 = 881216 bor -927242187531829389. +-927242187532022477 = 881216 bxor -927242187531829389. +-881217 = bnot(881216). +56397824 = 881216 bsl 6. +13769 = 881216 bsr 6. +-92294491442187688455153989533 = -92294491442187686323776125311 + -2131377864222. +-92294491442187684192398261089 = -92294491442187686323776125311 - -2131377864222. +196714436049505647464037636743433815523042 = -92294491442187686323776125311 * -2131377864222. +92294491442187686323776125311 = -(-92294491442187686323776125311). +-92294491442187686323776125311 = +(-92294491442187686323776125311). +43302735282876372 = -92294491442187686323776125311 div -2131377864222. +-1561548162727 = -92294491442187686323776125311 rem -2131377864222. +-92294491442187687148409847680 = -92294491442187686323776125311 band -2131377864222. +-1306744141853 = -92294491442187686323776125311 bor -2131377864222. +92294491442187685841665705827 = -92294491442187686323776125311 bxor -2131377864222. +92294491442187686323776125310 = bnot(-92294491442187686323776125311). +-185999584514065598597956584080419883018491093214177575881974373283864097380857203228341277386380643103031653648497557735646336491731819166395960639369110660948577337627072201396978938963758595137324517976756474055979267842414815940739328582451905282350545473628506864588391433882838514410717184 = -92294491442187686323776125311 bsl 878. +-1 = -92294491442187686323776125311 bsr 878. +-22992720593436056750377491 = -81183965279133325738952927 + 58191244685697268988575436. +-139375209964830594727528363 = -81183965279133325738952927 - 58191244685697268988575436. +-4724195988113198744171942818553380419018847992501172 = -81183965279133325738952927 * 58191244685697268988575436. +81183965279133325738952927 = -(-81183965279133325738952927). +-81183965279133325738952927 = +(-81183965279133325738952927). +-1 = -81183965279133325738952927 div 58191244685697268988575436. +-22992720593436056750377491 = -81183965279133325738952927 rem 58191244685697268988575436. +58029031944576824657589760 = -81183965279133325738952927 band 58191244685697268988575436. +-81021752538012881407967251 = -81183965279133325738952927 bor 58191244685697268988575436. +-139050784482589706065557011 = -81183965279133325738952927 bxor 58191244685697268988575436. +81183965279133325738952926 = bnot(-81183965279133325738952927). +-5019815681416656113511808829597582218059123923898989834827865951504562132517509866352730861760071653866933645628409284104571167935680767215508231731030047302186971796092169038304272610902626447392768 = -81183965279133325738952927 bsl 574. +-1 = -81183965279133325738952927 bsr 574. +-627171199928636384 = 3 + -627171199928636387. +627171199928636390 = 3 - -627171199928636387. +-1881513599785909161 = 3 * -627171199928636387. +-3 = -(3). +3 = +(3). +0 = 3 div -627171199928636387. +3 = 3 rem -627171199928636387. +1 = 3 band -627171199928636387. +-627171199928636385 = 3 bor -627171199928636387. +-627171199928636386 = 3 bxor -627171199928636387. +-4 = bnot(3). +14167099448608935641088 = 3 bsl 72. +0 = 3 bsr 72. +38489905028814522963407073 = 38489896817115623696432732 + 8211698899266974341. +38489888605416724429458391 = 38489896817115623696432732 - 8211698899266974341. +316067443326007786301602416749121180676529612 = 38489896817115623696432732 * 8211698899266974341. +-38489896817115623696432732 = -(38489896817115623696432732). +38489896817115623696432732 = +(38489896817115623696432732). +4687202 = 38489896817115623696432732 div 8211698899266974341. +5313073663031348850 = 38489896817115623696432732 rem 8211698899266974341. +8126112209232212484 = 38489896817115623696432732 band 8211698899266974341. +38489896902702313731194589 = 38489896817115623696432732 bor 8211698899266974341. +38489888776590104498982105 = 38489896817115623696432732 bxor 8211698899266974341. +-38489896817115623696432733 = bnot(38489896817115623696432732). +75175579720928952532095 = 38489896817115623696432732 bsl -9. +19706827170363199332573558784 = 38489896817115623696432732 bsr -9. +83662398216864836064980991875 = -577817779741 + 83662398216864836642798771616. +-83662398216864837220616551357 = -577817779741 - 83662398216864836642798771616. +-48341621185476237330836646511399250631456 = -577817779741 * 83662398216864836642798771616. +577817779741 = -(-577817779741). +-577817779741 = +(-577817779741). +0 = -577817779741 div 83662398216864836642798771616. +-577817779741 = -577817779741 rem 83662398216864836642798771616. +83662398216864836084310213024 = -577817779741 band 83662398216864836642798771616. +-19329221149 = -577817779741 bor 83662398216864836642798771616. +-83662398216864836103639434173 = -577817779741 bxor 83662398216864836642798771616. +577817779740 = bnot(-577817779741). +-18490168951712 = -577817779741 bsl 5. +-18056805617 = -577817779741 bsr 5. +-9323712223762171796121 = -9323712223762171796118 + -3. +-9323712223762171796115 = -9323712223762171796118 - -3. +27971136671286515388354 = -9323712223762171796118 * -3. +9323712223762171796118 = -(-9323712223762171796118). +-9323712223762171796118 = +(-9323712223762171796118). +3107904074587390598706 = -9323712223762171796118 div -3. +0 = -9323712223762171796118 rem -3. +-9323712223762171796120 = -9323712223762171796118 band -3. +-1 = -9323712223762171796118 bor -3. +9323712223762171796119 = -9323712223762171796118 bxor -3. +9323712223762171796117 = bnot(-9323712223762171796118). +-383156198468100171274531995553938956410245284103900601718134146024035993174671945925044898293687575318577045701862973654972998397835931164269051794643753412311088298486910253034674495588871621252033983025960411401743062972766355456 = -9323712223762171796118 bsl 693. +-1 = -9323712223762171796118 bsr 693. +3758818439164718652970 = 3758818439164718653841 + -871. +3758818439164718654712 = 3758818439164718653841 - -871. +-3273930860512469947495511 = 3758818439164718653841 * -871. +-3758818439164718653841 = -(3758818439164718653841). +3758818439164718653841 = +(3758818439164718653841). +-4315520596055934160 = 3758818439164718653841 div -871. +481 = 3758818439164718653841 rem -871. +3758818439164718653585 = 3758818439164718653841 band -871. +-615 = 3758818439164718653841 bor -871. +-3758818439164718654200 = 3758818439164718653841 bxor -871. +-3758818439164718653842 = bnot(3758818439164718653841). +0 = 3758818439164718653841 bsl -562. +56742558204536011717878679188974270513240470254145891506083143932073281639818006934936298751805558180191534955833936593373339751482539304001976191488311896199919676896644311542788491013259264 = 3758818439164718653841 bsr -562. +91757988939962461471635 = 91757988939962489784156 + -28312521. +91757988939962518096677 = 91757988939962489784156 - -28312521. +-2597899988780455731226202217276 = 91757988939962489784156 * -28312521. +-91757988939962489784156 = -(91757988939962489784156). +91757988939962489784156 = +(91757988939962489784156). +-3240897867765378 = 91757988939962489784156 div -28312521. +2086218 = 91757988939962489784156 rem -28312521. +91757988939962461471764 = 91757988939962489784156 band -28312521. +-129 = 91757988939962489784156 bor -28312521. +-91757988939962461471893 = 91757988939962489784156 bxor -28312521. +-91757988939962489784157 = bnot(91757988939962489784156). +1733259406022409871975898372007034246140002304 = 91757988939962489784156 bsl 74. +4 = 91757988939962489784156 bsr 74. +39565775828 = -21 + 39565775849. +-39565775870 = -21 - 39565775849. +-830881292829 = -21 * 39565775849. +21 = -(-21). +-21 = +(-21). +0 = -21 div 39565775849. +-21 = -21 rem 39565775849. +39565775849 = -21 band 39565775849. +-21 = -21 bor 39565775849. +-39565775870 = -21 bxor 39565775849. +20 = bnot(-21). +-336 = -21 bsl 4. +-2 = -21 bsr 4. +-29762862369475373945987344 = 5 + -29762862369475373945987349. +29762862369475373945987354 = 5 - -29762862369475373945987349. +-148814311847376869729936745 = 5 * -29762862369475373945987349. +-5 = -(5). +5 = +(5). +0 = 5 div -29762862369475373945987349. +5 = 5 rem -29762862369475373945987349. +1 = 5 band -29762862369475373945987349. +-29762862369475373945987345 = 5 bor -29762862369475373945987349. +-29762862369475373945987346 = 5 bxor -29762862369475373945987349. +-6 = bnot(5). +96714065569170333976494080 = 5 bsl 84. +0 = 5 bsr 84. +732729761416169004741 = 732729756148682423249 + 5267486581492. +732729750881195841757 = 732729756148682423249 - 5267486581492. +3859644158373089945319821673907508 = 732729756148682423249 * 5267486581492. +-732729756148682423249 = -(732729756148682423249). +732729756148682423249 = +(732729756148682423249). +139104247 = 732729756148682423249 div 5267486581492. +1647633626725 = 732729756148682423249 rem 5267486581492. +4434025915088 = 732729756148682423249 band 5267486581492. +732729756982143089653 = 732729756148682423249 bor 5267486581492. +732729752548117174565 = 732729756148682423249 bxor 5267486581492. +-732729756148682423250 = bnot(732729756148682423249). +23447352196757837543968 = 732729756148682423249 bsl 5. +22897804879646325726 = 732729756148682423249 bsr 5. +-4352599859673007 = -4352599857524451 + -2148556. +-4352599855375895 = -4352599857524451 - -2148556. +9351804539483304342756 = -4352599857524451 * -2148556. +4352599857524451 = -(-4352599857524451). +-4352599857524451 = +(-4352599857524451). +2025825651 = -4352599857524451 div -2148556. +-114495 = -4352599857524451 rem -2148556. +-4352599859654380 = -4352599857524451 band -2148556. +-18627 = -4352599857524451 bor -2148556. +4352599859635753 = -4352599857524451 bxor -2148556. +4352599857524450 = bnot(-4352599857524451). +-506710 = -4352599857524451 bsl -33. +-37388548081283553130708992 = -4352599857524451 bsr -33. +-94389634156317189166047 = -94389634156317189165519 + -528. +-94389634156317189164991 = -94389634156317189165519 - -528. +49837726834535475879394032 = -94389634156317189165519 * -528. +94389634156317189165519 = -(-94389634156317189165519). +-94389634156317189165519 = +(-94389634156317189165519). +178768246508176494631 = -94389634156317189165519 div -528. +-351 = -94389634156317189165519 rem -528. +-94389634156317189166032 = -94389634156317189165519 band -528. +-15 = -94389634156317189165519 bor -528. +94389634156317189166017 = -94389634156317189165519 bxor -528. +94389634156317189165518 = bnot(-94389634156317189165519). +-1 = -94389634156317189165519 bsl -481. +-589321407184680099467763885021504893476495349802993815326732172023506652597245345883037146499772326893673837721264247748151299039384987799013342753209972052494215282688 = -94389634156317189165519 bsr -481. +74772711469266263075409212497 = 2119146693595222 + 74772711469264143928715617275. +-74772711469262024782022022053 = 2119146693595222 - 74772711469264143928715617275. +158454344281240644616172070363307888720660050 = 2119146693595222 * 74772711469264143928715617275. +-2119146693595222 = -(2119146693595222). +2119146693595222 = +(2119146693595222). +0 = 2119146693595222 div 74772711469264143928715617275. +2119146693595222 = 2119146693595222 rem 74772711469264143928715617275. +425787105083474 = 2119146693595222 band 74772711469264143928715617275. +74772711469265837288304129023 = 2119146693595222 bor 74772711469264143928715617275. +74772711469265411501199045549 = 2119146693595222 bxor 74772711469264143928715617275. +-2119146693595223 = bnot(2119146693595222). +60 = 2119146693595222 bsl -45. +74560845778272347356034760704 = 2119146693595222 bsr -45. +-433169449654421572447807185 = 3451446756 + -433169449654421575899253941. +433169449654421579350700697 = 3451446756 - -433169449654421575899253941. +-1495061291808058669193887797484665396 = 3451446756 * -433169449654421575899253941. +-3451446756 = -(3451446756). +3451446756 = +(3451446756). +0 = 3451446756 div -433169449654421575899253941. +3451446756 = 3451446756 rem -433169449654421575899253941. +1143497024 = 3451446756 band -433169449654421575899253941. +-433169449654421573591304209 = 3451446756 bor -433169449654421575899253941. +-433169449654421574734801233 = 3451446756 bxor -433169449654421575899253941. +-3451446757 = bnot(3451446756). +1698155371193525204830545916836568128680441580998381568463828606592094114468682671168384424246732426433969671163465789195711765615185779492213847037840137881175115452783147995343129479623640605849293724317507773619519108156500008029348686509290662078665092776507457142784 = 3451446756 bsl 866. +0 = 3451446756 bsr 866. +76344137685153051759 = 58961 + 76344137685152992798. +-76344137685152933837 = 58961 - 76344137685152992798. +4501326702054305608362878 = 58961 * 76344137685152992798. +-58961 = -(58961). +58961 = +(58961). +0 = 58961 div 76344137685152992798. +58961 = 58961 rem 76344137685152992798. +34320 = 58961 band 76344137685152992798. +76344137685153017439 = 58961 bor 76344137685152992798. +76344137685152983119 = 58961 bxor 76344137685152992798. +-58962 = bnot(58961). +0 = 58961 bsl -42. +259313220341202944 = 58961 bsr -42. +57479277147034760219615969056 = -8862494328917399859 + 57479277155897254548533368915. +-57479277164759748877450768774 = -8862494328917399859 - 57479277155897254548533368915. +-509409767824410870945391245069230635419415982985 = -8862494328917399859 * 57479277155897254548533368915. +8862494328917399859 = -(-8862494328917399859). +-8862494328917399859 = +(-8862494328917399859). +0 = -8862494328917399859 div 57479277155897254548533368915. +-8862494328917399859 = -8862494328917399859 rem 57479277155897254548533368915. +57479277151278456879468134465 = -8862494328917399859 band 57479277155897254548533368915. +-4243696659852165409 = -8862494328917399859 bor 57479277155897254548533368915. +-57479277155522153539320299874 = -8862494328917399859 bxor 57479277155897254548533368915. +8862494328917399858 = bnot(-8862494328917399859). +-2215623582229349965 = -8862494328917399859 bsl -2. +-35449977315669599436 = -8862494328917399859 bsr -2. +-789815706 = -789767185 + -48521. +-789718664 = -789767185 - -48521. +38320293583385 = -789767185 * -48521. +789767185 = -(-789767185). +-789767185 = +(-789767185). +16276 = -789767185 div -48521. +-39389 = -789767185 rem -48521. +-789773721 = -789767185 band -48521. +-41985 = -789767185 bor -48521. +789731736 = -789767185 bxor -48521. +789767184 = bnot(-789767185). +-1 = -789767185 bsl -668. +-967244320475332459002335950829023241212009066219700749912658431836369087690997676597488152418437276434629255755917760744115452947683138425828558291918401735328264621736592953964668879409046635974873824215695360 = -789767185 bsr -668. +-777623247658461946715588637616 = -44827 + -777623247658461946715588592789. +777623247658461946715588547962 = -44827 - -777623247658461946715588592789. +34858517322785873685419689848952503 = -44827 * -777623247658461946715588592789. +44827 = -(-44827). +-44827 = +(-44827). +0 = -44827 div -777623247658461946715588592789. +-44827 = -44827 rem -777623247658461946715588592789. +-777623247658461946715588636575 = -44827 band -777623247658461946715588592789. +-1041 = -44827 bor -777623247658461946715588592789. +777623247658461946715588635534 = -44827 bxor -777623247658461946715588592789. +44826 = bnot(-44827). +-358616 = -44827 bsl 3. +-5604 = -44827 bsr 3. +-49423188549633 = 25351124379885 + -74774312929518. +100125437309403 = 25351124379885 - -74774312929518. +-1895612907496653945461945430 = 25351124379885 * -74774312929518. +-25351124379885 = -(25351124379885). +25351124379885 = +(25351124379885). +0 = 25351124379885 div -74774312929518. +25351124379885 = 25351124379885 rem -74774312929518. +20950926172160 = 25351124379885 band -74774312929518. +-70374114721793 = 25351124379885 bor -74774312929518. +-91325040893953 = 25351124379885 bxor -74774312929518. +-25351124379886 = bnot(25351124379885). +52597442651485657809365458667747892670808001914636976424691825090673452876305446441790869078292405009570560626596540131597379195232839616586590302364353984959784155371906169553655674683921530880 = 25351124379885 bsl 599. +0 = 25351124379885 bsr 599. +-15852865259102721198 = -9926283823219191664 + -5926581435883529534. +-3999702387335662130 = -9926283823219191664 - -5926581435883529534. +58828929434001848172249748630750604576 = -9926283823219191664 * -5926581435883529534. +9926283823219191664 = -(-9926283823219191664). +-9926283823219191664 = +(-9926283823219191664). +1 = -9926283823219191664 div -5926581435883529534. +-3999702387335662130 = -9926283823219191664 rem -5926581435883529534. +-15852528765024317312 = -9926283823219191664 band -5926581435883529534. +-336494078403886 = -9926283823219191664 bor -5926581435883529534. +15852192270945913426 = -9926283823219191664 bxor -5926581435883529534. +9926283823219191663 = bnot(-9926283823219191664). +-1547756045176818240766206999809915530671296664991964117799518055392269366077386494692881433839074405311077250537837886767801418064914093372206515291028891547675977370286094990394268275016242604106038028738327402925622139791354161601330758117019767057343663418879325827380964335218533457494233551068446561665024 = -9926283823219191664 bsl 964. +-1 = -9926283823219191664 bsr 964. +-383677947339064 = -383677947346213 + 7149. +-383677947353362 = -383677947346213 - 7149. +-2742913645578076737 = -383677947346213 * 7149. +383677947346213 = -(-383677947346213). +-383677947346213 = +(-383677947346213). +-53668757497 = -383677947346213 div 7149. +-160 = -383677947346213 rem 7149. +713 = -383677947346213 band 7149. +-383677947339777 = -383677947346213 bor 7149. +-383677947340490 = -383677947346213 bxor 7149. +383677947346212 = bnot(-383677947346213). +-184349993378748017410350293410895821521862783586301195774935674013710260738384110439146111760752677495343397910854837653850092153763712234228462046128933001276753302353480921523231388620474310418148418884596127970493618659407853109150585379373807238231576711160423795130368 = -383677947346213 bsl 856. +-1 = -383677947346213 bsr 856. +8912273195587815868165187 = 8912273195587893298126921 + -77429961734. +8912273195587970728088655 = 8912273195587893298126921 - -77429961734. +-690076972497324475707642546905241014 = 8912273195587893298126921 * -77429961734. +-8912273195587893298126921 = -(8912273195587893298126921). +8912273195587893298126921 = +(8912273195587893298126921). +-115101092600365 = 8912273195587893298126921 div -77429961734. +40793694011 = 8912273195587893298126921 rem -77429961734. +8912273195587815954481224 = 8912273195587893298126921 band -77429961734. +-86316037 = 8912273195587893298126921 bor -77429961734. +-8912273195587816040797261 = 8912273195587893298126921 bxor -77429961734. +-8912273195587893298126922 = bnot(8912273195587893298126921). +278508537362121665566466 = 8912273195587893298126921 bsl -5. +285192742258812585540061472 = 8912273195587893298126921 bsr -5. +-8319732734949941921 = 2 + -8319732734949941923. +8319732734949941925 = 2 - -8319732734949941923. +-16639465469899883846 = 2 * -8319732734949941923. +-2 = -(2). +2 = +(2). +0 = 2 div -8319732734949941923. +2 = 2 rem -8319732734949941923. +0 = 2 band -8319732734949941923. +-8319732734949941921 = 2 bor -8319732734949941923. +-8319732734949941921 = 2 bxor -8319732734949941923. +-3 = bnot(2). +0 = 2 bsl -349. +2293498615990071511610820895302086940796564989168281123737588839386922876088484808070018553110125686554624 = 2 bsr -349. +-55166512001 = -55166511776 + -225. +-55166511551 = -55166511776 - -225. +12412465149600 = -55166511776 * -225. +55166511776 = -(-55166511776). +-55166511776 = +(-55166511776). +245184496 = -55166511776 div -225. +-176 = -55166511776 rem -225. +-55166511872 = -55166511776 band -225. +-129 = -55166511776 bor -225. +55166511743 = -55166511776 bxor -225. +55166511775 = bnot(-55166511776). +-1 = -55166511776 bsl -632. +-983179429919357600188043312907429492583409892139791338942729556793990055834694805047122432028004044528336229548373177381065816092507597262686575422335137617441398222885097037637605200400385762127773696 = -55166511776 bsr -632. +44636453572121039829328985 = 44636453523244412987464786 + 48876626841864199. +44636453474367786145600587 = 44636453523244412987464786 - 48876626841864199. +2181679282399831671724744654409275106596414 = 44636453523244412987464786 * 48876626841864199. +-44636453523244412987464786 = -(44636453523244412987464786). +44636453523244412987464786 = +(44636453523244412987464786). +913247423 = 44636453523244412987464786 div 48876626841864199. +14979304734755609 = 44636453523244412987464786 rem 48876626841864199. +12705992542390274 = 44636453523244412987464786 band 48876626841864199. +44636453559415047286938711 = 44636453523244412987464786 bor 48876626841864199. +44636453546709054744548437 = 44636453523244412987464786 bxor 48876626841864199. +-44636453523244412987464787 = bnot(44636453523244412987464786). +147 = 44636453523244412987464786 bsl -78. +13490540290069638524711849676635183589775674179584 = 44636453523244412987464786 bsr -78. +6178626537631128165561247990 = 62599 + 6178626537631128165561185391. +-6178626537631128165561122792 = 62599 - 6178626537631128165561185391. +386775842629170992035964644291209 = 62599 * 6178626537631128165561185391. +-62599 = -(62599). +62599 = +(62599). +0 = 62599 div 6178626537631128165561185391. +62599 = 62599 rem 6178626537631128165561185391. +46087 = 62599 band 6178626537631128165561185391. +6178626537631128165561201903 = 62599 bor 6178626537631128165561185391. +6178626537631128165561155816 = 62599 bxor 6178626537631128165561185391. +-62600 = bnot(62599). +781673350004923190769026419951289670294225980530738116290529466062354581913514032215644166982686135610536024245075732746528591318191069487553834909696 = 62599 bsl 482. +0 = 62599 bsr 482. +61294794533664140628529 = 28755399394 + 61294794533635385229135. +-61294794533606629829741 = 28755399394 - 61294794533635385229135. +1762556297587853469034825130144190 = 28755399394 * 61294794533635385229135. +-28755399394 = -(28755399394). +28755399394 = +(28755399394). +0 = 28755399394 div 61294794533635385229135. +28755399394 = 28755399394 rem 61294794533635385229135. +8593347138 = 28755399394 band 61294794533635385229135. +61294794533655547281391 = 28755399394 bor 61294794533635385229135. +61294794533646953934253 = 28755399394 bxor 61294794533635385229135. +-28755399395 = bnot(28755399394). +224651557 = 28755399394 bsl -7. +3680691122432 = 28755399394 bsr -7. +68356591755465309388702963323 = 68356591755456717891361834647 + 8591497341128676. +68356591755448126394020705971 = 68356591755456717891361834647 - 8591497341128676. +587285476315624766804947477869971049062037372 = 68356591755456717891361834647 * 8591497341128676. +-68356591755456717891361834647 = -(68356591755456717891361834647). +68356591755456717891361834647 = +(68356591755456717891361834647). +7956307153611 = 68356591755456717891361834647 div 8591497341128676. +4747063712785611 = 68356591755456717891361834647 rem 8591497341128676. +141569639843460 = 68356591755456717891361834647 band 8591497341128676. +68356591755465167819063119863 = 68356591755456717891361834647 bor 8591497341128676. +68356591755465026249423276403 = 68356591755456717891361834647 bxor 8591497341128676. +-68356591755456717891361834648 = bnot(68356591755456717891361834647). +573416652452558267357221017014501376 = 68356591755456717891361834647 bsl 23. +8148740739280786262912 = 68356591755456717891361834647 bsr 23. +-699567528957588408229971773208 = -699567528956825442116545643412 + -762966113426129796. +-699567528956062476003119513616 = -699567528956825442116545643412 - -762966113426129796. +533746318647310620793763440997871100807844303952 = -699567528956825442116545643412 * -762966113426129796. +699567528956825442116545643412 = -(-699567528956825442116545643412). +-699567528956825442116545643412 = +(-699567528956825442116545643412). +916905111047 = -699567528956825442116545643412 div -762966113426129796. +-741903883730187000 = -699567528956825442116545643412 rem -762966113426129796. +-699567528957407700745095857044 = -699567528956825442116545643412 band -762966113426129796. +-180707484875916164 = -699567528956825442116545643412 bor -762966113426129796. +699567528957226993260219940880 = -699567528956825442116545643412 bxor -762966113426129796. +699567528956825442116545643411 = bnot(-699567528956825442116545643412). +-1550121224195987807290171107091258107712715916897584379572599658174498656050114252196127509785981291190843396381201329621527162385718421440264449420454387485687802987709033516486490246567477835931041196955025926459411521992418704737782360971317378993141120628074117433571666760150601966198593076802069987328 = -699567528956825442116545643412 bsl 918. +-1 = -699567528956825442116545643412 bsr 918. +-2968553792195197914198583324 = -2968553792195197914198583351 + 27. +-2968553792195197914198583378 = -2968553792195197914198583351 - 27. +-80150952389270343683361750477 = -2968553792195197914198583351 * 27. +2968553792195197914198583351 = -(-2968553792195197914198583351). +-2968553792195197914198583351 = +(-2968553792195197914198583351). +-109946436747970293118466050 = -2968553792195197914198583351 div 27. +-1 = -2968553792195197914198583351 rem 27. +9 = -2968553792195197914198583351 band 27. +-2968553792195197914198583333 = -2968553792195197914198583351 bor 27. +-2968553792195197914198583342 = -2968553792195197914198583351 bxor 27. +2968553792195197914198583350 = bnot(-2968553792195197914198583351). +-664188490871115306642579814060706102409828879569937769141553990272626475834572045731134930507314228990954986433495077258998829005959661816677464155727409238268814013379673829080983557475938736170397612032475671508364459503815492935041291646492770907720336592025769311712837632 = -2968553792195197914198583351 bsl 825. +-1 = -2968553792195197914198583351 bsr 825. +815573798945895524991106 = -441683913266449 + 815573799387579438257555. +-815573799829263351524004 = -441683913266449 - 815573799387579438257555. +-360225827271091913160959947957002272195 = -441683913266449 * 815573799387579438257555. +441683913266449 = -(-441683913266449). +-441683913266449 = +(-441683913266449). +0 = -441683913266449 div 815573799387579438257555. +-441683913266449 = -441683913266449 rem 815573799387579438257555. +815573799104386470379651 = -441683913266449 band 815573799387579438257555. +-158490945388545 = -441683913266449 bor 815573799387579438257555. +-815573799262877415768196 = -441683913266449 bxor 815573799387579438257555. +441683913266448 = bnot(-441683913266449). +-1932146918834075102100431195023309123629707192731767591505727311905482150279583583222046778003171933397097960701952 = -441683913266449 bsl 331. +-1 = -441683913266449 bsr 331. +52204 = 52158 + 46. +52112 = 52158 - 46. +2399268 = 52158 * 46. +-52158 = -(52158). +52158 = +(52158). +1133 = 52158 div 46. +40 = 52158 rem 46. +46 = 52158 band 46. +52158 = 52158 bor 46. +52112 = 52158 bxor 46. +-52159 = bnot(52158). +0 = 52158 bsl -52. +234898749364390330368 = 52158 bsr -52. +-97487593454442928269 = -4927 + -97487593454442923342. +97487593454442918415 = -4927 - -97487593454442923342. +480321372950040283306034 = -4927 * -97487593454442923342. +4927 = -(-4927). +-4927 = +(-4927). +0 = -4927 div -97487593454442923342. +-4927 = -4927 rem -97487593454442923342. +-97487593454442928000 = -4927 band -97487593454442923342. +-269 = -4927 bor -97487593454442923342. +97487593454442927731 = -4927 bxor -97487593454442923342. +4926 = bnot(-4927). +-14589799195796190115888637427625179461957316219966820150531977446278291785975988233475185242269022363399606798448114009259810209040362721455852515037780569978447627385816054314892114758123179507549420923285371859618471253297332224 = -4927 bsl 749. +-1 = -4927 bsr 749. +761499775066582643 = -3473149426889489 + 764972924493472132. +-768446073920361621 = -3473149426889489 - 764972924493472132. +-2656865274290479077637570265220548 = -3473149426889489 * 764972924493472132. +3473149426889489 = -(-3473149426889489). +-3473149426889489 = +(-3473149426889489). +0 = -3473149426889489 div 764972924493472132. +-3473149426889489 = -3473149426889489 rem 764972924493472132. +761574600322089092 = -3473149426889489 band 764972924493472132. +-74825255506449 = -3473149426889489 bor 764972924493472132. +-761649425577595541 = -3473149426889489 bxor 764972924493472132. +3473149426889488 = bnot(-3473149426889489). +-512546388860651254601660862186913792 = -3473149426889489 bsl 67. +-1 = -3473149426889489 bsr 67. +-29167626795 = -29167626868 + 73. +-29167626941 = -29167626868 - 73. +-2129236761364 = -29167626868 * 73. +29167626868 = -(-29167626868). +-29167626868 = +(-29167626868). +-399556532 = -29167626868 div 73. +-32 = -29167626868 rem 73. +8 = -29167626868 band 73. +-29167626803 = -29167626868 bor 73. +-29167626811 = -29167626868 bxor 73. +29167626867 = bnot(-29167626868). +-1 = -29167626868 bsl -296. +-3713469079651023032800980145115508414591077540621460200026867016400652828280866359537842689983643648 = -29167626868 bsr -296. +-5646468003438 = -5646468742754 + 739316. +-5646469482070 = -5646468742754 - 739316. +-4174524685017916264 = -5646468742754 * 739316. +5646468742754 = -(-5646468742754). +-5646468742754 = +(-5646468742754). +-7637422 = -5646468742754 div 739316. +-459402 = -5646468742754 rem 739316. +524692 = -5646468742754 band 739316. +-5646468528130 = -5646468742754 bor 739316. +-5646469052822 = -5646468742754 bxor 739316. +5646468742753 = bnot(-5646468742754). +-176452148212 = -5646468742754 bsl -5. +-180686999768128 = -5646468742754 bsr -5. +-956277620367771238126145 = -7868127313336278 + -956277612499643924789867. +956277604631516611453589 = -7868127313336278 - -956277612499643924789867. +7524114002040453690389825588077857895026 = -7868127313336278 * -956277612499643924789867. +7868127313336278 = -(-7868127313336278). +-7868127313336278 = +(-7868127313336278). +0 = -7868127313336278 div -956277612499643924789867. +-7868127313336278 = -7868127313336278 rem -956277612499643924789867. +-956277617377078110306304 = -7868127313336278 band -956277612499643924789867. +-2990693127819841 = -7868127313336278 bor -956277612499643924789867. +956277614386384982486463 = -7868127313336278 bxor -956277612499643924789867. +7868127313336277 = bnot(-7868127313336278). +-67586698983087317320728576 = -7868127313336278 bsl 33. +-915971 = -7868127313336278 bsr 33. +-3404395 = -3336216 + -68179. +-3268037 = -3336216 - -68179. +227459870664 = -3336216 * -68179. +3336216 = -(-3336216). +-3336216 = +(-3336216). +48 = -3336216 div -68179. +-63624 = -3336216 rem -68179. +-3402328 = -3336216 band -68179. +-2067 = -3336216 bor -68179. +3400261 = -3336216 bxor -68179. +3336215 = bnot(-3336216). +-1 = -3336216 bsl -55. +-120199849075419893465088 = -3336216 bsr -55. +-26667627288156133159209 = -73524972633286392 + -26667553763183499872817. +26667480238210866586425 = -73524972633286392 - -26667553763183499872817. +1960731160634760365163374554512736806264 = -73524972633286392 * -26667553763183499872817. +73524972633286392 = -(-73524972633286392). +-73524972633286392 = +(-73524972633286392). +0 = -73524972633286392 div -26667553763183499872817. +-73524972633286392 = -73524972633286392 rem -26667553763183499872817. +-26667625880162171580152 = -73524972633286392 band -26667553763183499872817. +-1407993961579057 = -73524972633286392 bor -26667553763183499872817. +26667624472168210001095 = -73524972633286392 bxor -26667553763183499872817. +73524972633286391 = bnot(-73524972633286392). +-132313005449321260680774500200028140830168861061069117670914111166517837616265409926801035271503411746776605137121977062322282496434290842261606645221444297756607760213967001092096 = -73524972633286392 bsl 539. +-1 = -73524972633286392 bsr 539. +546126779234557 = 83 + 546126779234474. +-546126779234391 = 83 - 546126779234474. +45328522676461342 = 83 * 546126779234474. +-83 = -(83). +83 = +(83). +0 = 83 div 546126779234474. +83 = 83 rem 546126779234474. +2 = 83 band 546126779234474. +546126779234555 = 83 bor 546126779234474. +546126779234553 = 83 bxor 546126779234474. +-84 = bnot(83). +332 = 83 bsl 2. +20 = 83 bsr 2. +-738133514617696188442939210579 = -738133514617696233638262947878 + 45195323737299. +-738133514617696278833586685177 = -738133514617696233638262947878 - 45195323737299. +-33360183154497104989277574453536007801501522 = -738133514617696233638262947878 * 45195323737299. +738133514617696233638262947878 = -(-738133514617696233638262947878). +-738133514617696233638262947878 = +(-738133514617696233638262947878). +-16332077161525586 = -738133514617696233638262947878 div 45195323737299. +-42488331915664 = -738133514617696233638262947878 rem 45195323737299. +1103137899730 = -738133514617696233638262947878 band 45195323737299. +-738133514617696189546077110309 = -738133514617696233638262947878 bor 45195323737299. +-738133514617696190649215010039 = -738133514617696233638262947878 bxor 45195323737299. +738133514617696233638262947877 = bnot(-738133514617696233638262947878). +-25362074442916346130709715643076500783104 = -738133514617696233638262947878 bsl 35. +-21482512663866400068 = -738133514617696233638262947878 bsr 35. +7373598033 = 7373916289 + -318256. +7374234545 = 7373916289 - -318256. +-2346793102471984 = 7373916289 * -318256. +-7373916289 = -(7373916289). +7373916289 = +(7373916289). +-23169 = 7373916289 div -318256. +243025 = 7373916289 rem -318256. +7373652096 = 7373916289 band -318256. +-54063 = 7373916289 bor -318256. +-7373706159 = 7373916289 bxor -318256. +-7373916290 = bnot(7373916289). +115217442 = 7373916289 bsl -6. +471930642496 = 7373916289 bsr -6. +-9555122457769466332373611435 = 4172342184 + -9555122457769466336545953619. +9555122457769466340718295803 = 4172342184 - -9555122457769466336545953619. +-39867240503837302943138623139061163896 = 4172342184 * -9555122457769466336545953619. +-4172342184 = -(4172342184). +4172342184 = +(4172342184). +0 = 4172342184 div -9555122457769466336545953619. +4172342184 = 4172342184 rem -9555122457769466336545953619. +2021695656 = 4172342184 band -9555122457769466336545953619. +-9555122457769466334395307091 = 4172342184 bor -9555122457769466336545953619. +-9555122457769466336417002747 = 4172342184 bxor -9555122457769466336545953619. +-4172342185 = bnot(4172342184). +0 = 4172342184 bsl -372. +40136389791856951738794660592982613363559313877413175890401099927085788488463139812582073973306647849955782653992253784064 = 4172342184 bsr -372. +363969588297217972 = -996737648375349 + 364966325945593321. +-365963063593968670 = -996737648375349 - 364966325945593321. +-363775677459201808215401515444029 = -996737648375349 * 364966325945593321. +996737648375349 = -(-996737648375349). +-996737648375349 = +(-996737648375349). +0 = -996737648375349 div 364966325945593321. +-996737648375349 = -996737648375349 rem 364966325945593321. +364814043308902857 = -996737648375349 band 364966325945593321. +-844455011684885 = -996737648375349 bor 364966325945593321. +-365658498320587742 = -996737648375349 bxor 364966325945593321. +996737648375348 = bnot(-996737648375349). +-574580134631598876693413926797312 = -996737648375349 bsl 59. +-1 = -996737648375349 bsr 59. +-9734193829925 = -717566 + -9734193112359. +9734192394793 = -717566 - -9734193112359. +6984926014862998194 = -717566 * -9734193112359. +717566 = -(-717566). +-717566 = +(-717566). +0 = -717566 div -9734193112359. +-717566 = -717566 rem -9734193112359. +-9734193149952 = -717566 band -9734193112359. +-679973 = -717566 bor -9734193112359. +9734192469979 = -717566 bxor -9734193112359. +717565 = bnot(-717566). +-44848 = -717566 bsl -4. +-11481056 = -717566 bsr -4. +678175877952508232 = 21487329859 + 678175856465178373. +-678175834977848514 = 21487329859 - 678175856465178373. +14572188330277125447923939407 = 21487329859 * 678175856465178373. +-21487329859 = -(21487329859). +21487329859 = +(21487329859). +0 = 21487329859 div 678175856465178373. +21487329859 = 21487329859 rem 678175856465178373. +4305068545 = 21487329859 band 678175856465178373. +678175873647439687 = 21487329859 bor 678175856465178373. +678175869342371142 = 21487329859 bxor 678175856465178373. +-21487329860 = bnot(21487329859). +5500756443904 = 21487329859 bsl 8. +83934882 = 21487329859 bsr 8. +7286046216 = -216257 + 7286262473. +-7286478730 = -216257 - 7286262473. +-1575705263623561 = -216257 * 7286262473. +216257 = -(-216257). +-216257 = +(-216257). +0 = -216257 div 7286262473. +-216257 = -216257 rem 7286262473. +7286063625 = -216257 band 7286262473. +-17409 = -216257 bor 7286262473. +-7286081034 = -216257 bxor 7286262473. +216256 = bnot(-216257). +-1857633485062144 = -216257 bsl 33. +-1 = -216257 bsr 33. +-6764481016209013 = 888466865577671 + -7652947881786684. +8541414747364355 = 888466865577671 - -7652947881786684. +-6799390616960291788045255532964 = 888466865577671 * -7652947881786684. +-888466865577671 = -(888466865577671). +888466865577671 = +(888466865577671). +0 = 888466865577671 div -7652947881786684. +888466865577671 = 888466865577671 rem -7652947881786684. +8856356815556 = 888466865577671 band -7652947881786684. +-6773337373024569 = 888466865577671 bor -7652947881786684. +-6782193729840125 = 888466865577671 bxor -7652947881786684. +-888466865577672 = bnot(888466865577671). +137483588309622589200810999915511218700288 = 888466865577671 bsl 87. +0 = 888466865577671 bsr 87. +91490331573054849644778 = 99741621496377689556299 + -8251289923322839911521. +107992911419700529467820 = 99741621496377689556299 - -8251289923322839911521. +-822997036388941987096763924793330974908220779 = 99741621496377689556299 * -8251289923322839911521. +-99741621496377689556299 = -(99741621496377689556299). +99741621496377689556299 = +(99741621496377689556299). +-12 = 99741621496377689556299 div -8251289923322839911521. +726142416503610618047 = 99741621496377689556299 rem -8251289923322839911521. +94447332200778076029195 = 99741621496377689556299 band -8251289923322839911521. +-2957000627723226384417 = 99741621496377689556299 bor -8251289923322839911521. +-97404332828501302413612 = 99741621496377689556299 bxor -8251289923322839911521. +-99741621496377689556300 = bnot(99741621496377689556299). +4174765856565762433809785303436052549481744663516623317101140077233477255380204318557841012624809946662412087062564502736088945479821863479435710747619717167586245784348605908982209472591040160588804704214594321655377727921255724473008462453546458253110240990996582037341144319885430793582000606583769395334471197239803904 = 99741621496377689556299 bsl 992. +0 = 99741621496377689556299 bsr 992. +724593654925448350082 = 868413935 + 724593654924579936147. +-724593654923711522212 = 868413935 - 724593654924579936147. +629247227149086590571465008445 = 868413935 * 724593654924579936147. +-868413935 = -(868413935). +868413935 = +(868413935). +0 = 868413935 div 724593654924579936147. +868413935 = 868413935 rem 724593654924579936147. +293769603 = 868413935 band 724593654924579936147. +724593654925154580479 = 868413935 bor 724593654924579936147. +724593654924860810876 = 868413935 bxor 724593654924579936147. +-868413936 = bnot(868413935). +8009704804494020882968084480 = 868413935 bsl 63. +0 = 868413935 bsr 63. +8632255073244542809708331575 = -7118711883835919751124254 + 8639373785128378729459455829. +-8646492497012214649210580083 = -7118711883835919751124254 - 8639373785128378729459455829. +-61501212833093901526261388977476702258823433803576566 = -7118711883835919751124254 * 8639373785128378729459455829. +7118711883835919751124254 = -(-7118711883835919751124254). +-7118711883835919751124254 = +(-7118711883835919751124254). +0 = -7118711883835919751124254 div 8639373785128378729459455829. +-7118711883835919751124254 = -7118711883835919751124254 rem 8639373785128378729459455829. +8639062071729512996535304768 = -7118711883835919751124254 band 8639373785128378729459455829. +-6806998484970186826973193 = -7118711883835919751124254 bor 8639373785128378729459455829. +-8645869070214483183362277961 = -7118711883835919751124254 bxor 8639373785128378729459455829. +7118711883835919751124253 = bnot(-7118711883835919751124254). +-771813 = -7118711883835919751124254 bsl -63. +-65658528127798005347284574349651537121247232 = -7118711883835919751124254 bsr -63. +-846509452415985654555762 = -839311283762714365725835 + -7198168653271288829927. +-832113115109443076895908 = -839311283762714365725835 - -7198168653271288829927. +6041504173117654213676998143437530729225064045 = -839311283762714365725835 * -7198168653271288829927. +839311283762714365725835 = -(-839311283762714365725835). +-839311283762714365725835 = +(-839311283762714365725835). +116 = -839311283762714365725835 div -7198168653271288829927. +-4323719983244861454303 = -839311283762714365725835 rem -7198168653271288829927. +-839386225952523109916655 = -839311283762714365725835 band -7198168653271288829927. +-7123226463462544639107 = -839311283762714365725835 bor -7198168653271288829927. +832262999489060565277548 = -839311283762714365725835 bxor -7198168653271288829927. +839311283762714365725834 = bnot(-839311283762714365725835). +-26857961080406859703226720 = -839311283762714365725835 bsl 5. +-26228477617584823928933 = -839311283762714365725835 bsr 5. +59337771524502253278240 = -311674139136692 + 59337771836176392414932. +-59337772147850531551624 = -311674139136692 - 59337771836176392414932. +-18494048955329724865880685275529884944 = -311674139136692 * 59337771836176392414932. +311674139136692 = -(-311674139136692). +-311674139136692 = +(-311674139136692). +0 = -311674139136692 div 59337771836176392414932. +-311674139136692 = -311674139136692 rem 59337771836176392414932. +59337771545891229279300 = -311674139136692 band 59337771836176392414932. +-21388976001060 = -311674139136692 bor 59337771836176392414932. +-59337771567280205280360 = -311674139136692 bxor 59337771836176392414932. +311674139136691 = bnot(-311674139136692). +-9739816848022 = -311674139136692 bsl -5. +-9973572452374144 = -311674139136692 bsr -5. +7384361237883868414254203561 = 7384361237883874829616473378 + -6415362269817. +7384361237883881244978743195 = 7384361237883874829616473378 - -6415362269817. +-47373352472219367116791452785860833431826 = 7384361237883874829616473378 * -6415362269817. +-7384361237883874829616473378 = -(7384361237883874829616473378). +7384361237883874829616473378 = +(7384361237883874829616473378). +-1151043530717793 = 7384361237883874829616473378 div -6415362269817. +565867719497 = 7384361237883874829616473378 rem -6415362269817. +7384361237883868489432974594 = 7384361237883874829616473378 band -6415362269817. +-75178771033 = 7384361237883874829616473378 bor -6415362269817. +-7384361237883868564611745627 = 7384361237883874829616473378 bxor -6415362269817. +-7384361237883874829616473379 = bnot(7384361237883874829616473378). +4059595522375848785786921648814674673664 = 7384361237883874829616473378 bsl 39. +13432074843665531 = 7384361237883874829616473378 bsr 39. +-3977553155326023397025 = -3977553156125337758647 + 799314361622. +-3977553156924652120269 = -3977553156125337758647 - 799314361622. +-3179315361805895649572059115445434 = -3977553156125337758647 * 799314361622. +3977553156125337758647 = -(-3977553156125337758647). +-3977553156125337758647 = +(-3977553156125337758647). +-4976206292 = -3977553156125337758647 div 799314361622. +-535978033023 = -3977553156125337758647 rem 799314361622. +249548575744 = -3977553156125337758647 band 799314361622. +-3977553155575571972769 = -3977553156125337758647 bor 799314361622. +-3977553155825120548513 = -3977553156125337758647 bxor 799314361622. +3977553156125337758646 = bnot(-3977553156125337758647). +-1 = -3977553156125337758647 bsl -94. +-78783556965655822831177085280930750212150130638848 = -3977553156125337758647 bsr -94. +-632628718016347 = -632621446787599 + -7271228748. +-632614175558851 = -632621446787599 - -7271228748. +4599935250483342098696052 = -632621446787599 * -7271228748. +632621446787599 = -(-632621446787599). +-632621446787599 = +(-632621446787599). +87003 = -632621446787599 div -7271228748. +-2732025355 = -632621446787599 rem -7271228748. +-632621738424144 = -632621446787599 band -7271228748. +-6979592203 = -632621446787599 bor -7271228748. +632614758831941 = -632621446787599 bxor -7271228748. +632621446787598 = bnot(-632621446787599). +-9206 = -632621446787599 bsl -36. +-43473414795215071413796864 = -632621446787599 bsr -36. +929613671737385374580 = 859391 + 929613671737384515189. +-929613671737383655798 = 859391 - 929613671737384515189. +798901622968062615892789899 = 859391 * 929613671737384515189. +-859391 = -(859391). +859391 = +(859391). +0 = 859391 div 929613671737384515189. +859391 = 859391 rem 929613671737384515189. +267381 = 859391 band 929613671737384515189. +929613671737385107199 = 859391 bor 929613671737384515189. +929613671737384839818 = 859391 bxor 929613671737384515189. +-859392 = bnot(859391). +472455198653022208 = 859391 bsl 39. +0 = 859391 bsr 39. +75357881755642898911906 = 75357881755569421413484 + 73477498422. +75357881755495943915062 = 75357881755569421413484 - 73477498422. +5537108637780114751620723619522248 = 75357881755569421413484 * 73477498422. +-75357881755569421413484 = -(75357881755569421413484). +75357881755569421413484 = +(75357881755569421413484). +1025591281330 = 75357881755569421413484 div 73477498422. +27388352224 = 75357881755569421413484 rem 73477498422. +4446594084 = 75357881755569421413484 band 73477498422. +75357881755638452317822 = 75357881755569421413484 bor 73477498422. +75357881755634005723738 = 75357881755569421413484 bxor 73477498422. +-75357881755569421413485 = bnot(75357881755569421413484). +1205726108089110742615744 = 75357881755569421413484 bsl 4. +4709867609723088838342 = 75357881755569421413484 bsr 4. +52686088 = -81126 + 52767214. +-52848340 = -81126 - 52767214. +-4280793002964 = -81126 * 52767214. +81126 = -(-81126). +-81126 = +(-81126). +0 = -81126 div 52767214. +-81126 = -81126 rem 52767214. +52691210 = -81126 band 52767214. +-5122 = -81126 bor 52767214. +-52696332 = -81126 bxor 52767214. +81125 = bnot(-81126). +-1 = -81126 bsl -78. +-24518829010514101606803308544 = -81126 bsr -78. +-93444457447505 = -93444456497546 + -949959. +-93444455547587 = -93444456497546 - -949959. +88768402449952300614 = -93444456497546 * -949959. +93444456497546 = -(-93444456497546). +-93444456497546 = +(-93444456497546). +98366831 = -93444456497546 div -949959. +-87617 = -93444456497546 rem -949959. +-93444457299920 = -93444456497546 band -949959. +-147585 = -93444456497546 bor -949959. +93444457152335 = -93444456497546 bxor -949959. +93444456497545 = bnot(-93444456497546). +-1 = -93444456497546 bsl -914. +-12941051909268604697162829316830566897993099152071438805265906320814944091424858349699489680718123770888301404623392627447633281381525770576269811087080625668986264684171387393369784316629809758745706270318418308651539390272376226390091132313131238731721120970038334365730701400102261489664 = -93444456497546 bsr -914. +-5617861855288475533985269679 = 645987691562896 + -5617861855289121521676832575. +5617861855289767509368395471 = 645987691562896 - -5617861855289121521676832575. +-3629069611417467716101248871383636674137200 = 645987691562896 * -5617861855289121521676832575. +-645987691562896 = -(645987691562896). +645987691562896 = +(645987691562896). +0 = 645987691562896 div -5617861855289121521676832575. +645987691562896 = 645987691562896 rem -5617861855289121521676832575. +636637136552064 = 645987691562896 band -5617861855289121521676832575. +-5617861855289112171121821743 = 645987691562896 bor -5617861855289121521676832575. +-5617861855289748808258373807 = 645987691562896 bxor -5617861855289121521676832575. +-645987691562897 = bnot(645987691562896). +363658740876073166051634839552 = 645987691562896 bsl 49. +1 = 645987691562896 bsr 49. +66715149278699370 = -48844 + 66715149278748214. +-66715149278797058 = -48844 - 66715149278748214. +-3258634751371177764616 = -48844 * 66715149278748214. +48844 = -(-48844). +-48844 = +(-48844). +0 = -48844 div 66715149278748214. +-48844 = -48844 rem 66715149278748214. +66715149278707764 = -48844 band 66715149278748214. +-8394 = -48844 bor 66715149278748214. +-66715149278716158 = -48844 bxor 66715149278748214. +48843 = bnot(-48844). +-1 = -48844 bsl -38. +-13426136486772736 = -48844 bsr -38. +3295561145144957083124548 = 3295561145144956985824896 + 97299652. +3295561145144956888525244 = 3295561145144956985824896 - 97299652. +320656952567325804275731313736192 = 3295561145144956985824896 * 97299652. +-3295561145144956985824896 = -(3295561145144956985824896). +3295561145144956985824896 = +(3295561145144956985824896). +33870225405790320 = 3295561145144956985824896 div 97299652. +64856256 = 3295561145144956985824896 rem 97299652. +25691264 = 3295561145144956985824896 band 97299652. +3295561145144957057433284 = 3295561145144956985824896 bor 97299652. +3295561145144957031742020 = 3295561145144956985824896 bxor 97299652. +-3295561145144956985824897 = bnot(3295561145144956985824896). +259703441323196961676360460665136735063618879506226750493095879826011849090010994459984645721689952198507282266369597144389258950003782582272 = 3295561145144956985824896 bsl 385. +0 = 3295561145144956985824896 bsr 385. +-986476643886792959314064916 = 615218779 + -986476643886792959929283695. +986476643886792960544502474 = 615218779 - -986476643886792959929283695. +-606898956364050579033489841182508405 = 615218779 * -986476643886792959929283695. +-615218779 = -(615218779). +615218779 = +(615218779). +0 = 615218779 div -986476643886792959929283695. +615218779 = 615218779 rem -986476643886792959929283695. +69798417 = 615218779 band -986476643886792959929283695. +-986476643886792959383863333 = 615218779 bor -986476643886792959929283695. +-986476643886792959453661750 = 615218779 bxor -986476643886792959929283695. +-615218780 = bnot(615218779). +18 = 615218779 bsl -25. +20643316685078528 = 615218779 bsr -25. +-467349317662454183287639774 = 64746241233363 + -467349317662518929528873137. +467349317662583675770106500 = 64746241233363 - -467349317662518929528873137. +-30259111661625046096016841538274438869731 = 64746241233363 * -467349317662518929528873137. +-64746241233363 = -(64746241233363). +64746241233363 = +(64746241233363). +0 = 64746241233363 div -467349317662518929528873137. +64746241233363 = 64746241233363 rem -467349317662518929528873137. +9632143741251 = 64746241233363 band -467349317662518929528873137. +-467349317662463815431381025 = 64746241233363 bor -467349317662518929528873137. +-467349317662473447575122276 = 64746241233363 bxor -467349317662518929528873137. +-64746241233364 = bnot(64746241233363). +1011660019271 = 64746241233363 bsl -6. +4143759438935232 = 64746241233363 bsr -6. +35450086531620560507 = 3341273982796755 + 35446745257637763752. +-35443403983654966997 = 3341273982796755 - 35446745257637763752. +118437287704169318322969476922224760 = 3341273982796755 * 35446745257637763752. +-3341273982796755 = -(3341273982796755). +3341273982796755 = +(3341273982796755). +0 = 3341273982796755 div 35446745257637763752. +3341273982796755 = 3341273982796755 rem 35446745257637763752. +2254002062525056 = 3341273982796755 band 35446745257637763752. +35447832529558035451 = 3341273982796755 bor 35446745257637763752. +35445578527495510395 = 3341273982796755 bxor 35446745257637763752. +-3341273982796756 = bnot(3341273982796755). +0 = 3341273982796755 bsl -582. +52889512678192664732690770583278780993203394534456274139414018863445336544367899815668028889670017211503927199630045246956599926056869252654122021934322204013537551648566187968385045254635520 = 3341273982796755 bsr -582. +578708048628698322701 = -8487932719457493135 + 587195981348155815836. +-595683914067613308971 = -8487932719457493135 - 587195981348155815836. +-4984079982818963609910892068739294285860 = -8487932719457493135 * 587195981348155815836. +8487932719457493135 = -(-8487932719457493135). +-8487932719457493135 = +(-8487932719457493135). +0 = -8487932719457493135 div 587195981348155815836. +-8487932719457493135 = -8487932719457493135 rem 587195981348155815836. +581085949258189772560 = -8487932719457493135 band 587195981348155815836. +-2377900629491449859 = -8487932719457493135 bor 587195981348155815836. +-583463849887681222419 = -8487932719457493135 bxor 587195981348155815836. +8487932719457493134 = bnot(-8487932719457493135). +-33155987185380833 = -8487932719457493135 bsl -8. +-2172910776181118242560 = -8487932719457493135 bsr -8. +-98251539676273547556103585 = -7652797965119 + -98251539676265894758138466. +98251539676258241960173347 = -7652797965119 - -98251539676265894758138466. +751899182904336331425461861269240167454 = -7652797965119 * -98251539676265894758138466. +7652797965119 = -(-7652797965119). +-7652797965119 = +(-7652797965119). +0 = -7652797965119 div -98251539676265894758138466. +-7652797965119 = -7652797965119 rem -98251539676265894758138466. +-98251539676268660856316800 = -7652797965119 band -98251539676265894758138466. +-4886699786785 = -7652797965119 bor -98251539676265894758138466. +98251539676263774156530015 = -7652797965119 bxor -98251539676265894758138466. +7652797965118 = bnot(-7652797965119). +-256785288930323857408 = -7652797965119 bsl 25. +-228072 = -7652797965119 bsr 25. +-938601950 = -934814639 + -3787311. +-931027328 = -934814639 - -3787311. +3540433765245729 = -934814639 * -3787311. +934814639 = -(-934814639). +-934814639 = +(-934814639). +246 = -934814639 div -3787311. +-3136133 = -934814639 rem -3787311. +-934931375 = -934814639 band -3787311. +-3670575 = -934814639 bor -3787311. +931260800 = -934814639 bxor -3787311. +934814638 = bnot(-934814639). +-3651620 = -934814639 bsl -8. +-239312547584 = -934814639 bsr -8. +-387581 = -656 + -386925. +386269 = -656 - -386925. +253822800 = -656 * -386925. +656 = -(-656). +-656 = +(-656). +0 = -656 div -386925. +-656 = -656 rem -386925. +-387056 = -656 band -386925. +-525 = -656 bor -386925. +386531 = -656 bxor -386925. +655 = bnot(-656). +-2624 = -656 bsl 2. +-164 = -656 bsr 2. +-6514808036364428552 = -896184894532265 + -6513911851469896287. +6513015666575364022 = -896184894532265 - -6513911851469896287. +5837669405602020039778712925200055 = -896184894532265 * -6513911851469896287. +896184894532265 = -(-896184894532265). +-896184894532265 = +(-896184894532265). +0 = -896184894532265 div -6513911851469896287. +-896184894532265 = -896184894532265 rem -6513911851469896287. +-6514245013329410815 = -896184894532265 band -6513911851469896287. +-563023035017737 = -896184894532265 bor -6513911851469896287. +6513681990294393078 = -896184894532265 bxor -6513911851469896287. +896184894532264 = bnot(-896184894532265). +-2116056754196618103829184408945950720 = -896184894532265 bsl 71. +-1 = -896184894532265 bsr 71. +-97222758789292894469424106674 = -97222758789292894469423252399 + -854275. +-97222758789292894469422398124 = -97222758789292894469423252399 - -854275. +83054972264723187422866548943155725 = -97222758789292894469423252399 * -854275. +97222758789292894469423252399 = -(-97222758789292894469423252399). +-97222758789292894469423252399 = +(-97222758789292894469423252399). +113807332286784576944687 = -97222758789292894469423252399 div -854275. +-765474 = -97222758789292894469423252399 rem -854275. +-97222758789292894469423582127 = -97222758789292894469423252399 band -854275. +-524547 = -97222758789292894469423252399 bor -854275. +97222758789292894469423057580 = -97222758789292894469423252399 bxor -854275. +97222758789292894469423252398 = bnot(-97222758789292894469423252399). +-388891035157171577877693009596 = -97222758789292894469423252399 bsl 2. +-24305689697323223617355813100 = -97222758789292894469423252399 bsr 2. +45314799959449834 = 8619 + 45314799959441215. +-45314799959432596 = 8619 - 45314799959441215. +390568260850423832085 = 8619 * 45314799959441215. +-8619 = -(8619). +8619 = +(8619). +0 = 8619 div 45314799959441215. +8619 = 8619 rem 45314799959441215. +8491 = 8619 band 45314799959441215. +45314799959441343 = 8619 bor 45314799959441215. +45314799959432852 = 8619 bxor 45314799959441215. +-8620 = bnot(8619). +7941353061410367410881337630258273820999253905949536145550420435013924476478987049836505430738828348984354473728064838669707682843096139575206787552025978320364779864064 = 8619 bsl 548. +0 = 8619 bsr 548. +-567484289988620768675110 = 832462677188 + -567484289989453231352298. +567484289990285694029486 = 832462677188 - -567484289989453231352298. +-472409491306751585255851530675978024 = 832462677188 * -567484289989453231352298. +-832462677188 = -(832462677188). +832462677188 = +(832462677188). +0 = 832462677188 div -567484289989453231352298. +832462677188 = 832462677188 rem -567484289989453231352298. +1107297284 = 832462677188 band -567484289989453231352298. +-567484289988621875972394 = 832462677188 bor -567484289989453231352298. +-567484289988622983269678 = 832462677188 bxor -567484289989453231352298. +-832462677189 = bnot(832462677188). +128817359912715694748896543518452875264 = 832462677188 bsl 87. +0 = 832462677188 bsr 87. +823334994347687588935276277 = -8726434876 + 823334994347687597661711153. +-823334994347687606388146029 = -8726434876 - 823334994347687597661711153. +-7184779209306923922187812255377372028 = -8726434876 * 823334994347687597661711153. +8726434876 = -(-8726434876). +-8726434876 = +(-8726434876). +0 = -8726434876 div 823334994347687597661711153. +-8726434876 = -8726434876 rem 823334994347687597661711153. +823334994347687597659466496 = -8726434876 band 823334994347687597661711153. +-8724190219 = -8726434876 bor 823334994347687597661711153. +-823334994347687606383656715 = -8726434876 bxor 823334994347687597661711153. +8726434875 = bnot(-8726434876). +-2637403108695496227490767824748544 = -8726434876 bsl 78. +-1 = -8726434876 bsr 78. +509565608112303867308591 = -9933529355932531354156 + 519499137468236398662747. +-529432666824168930016903 = -9933529355932531354156 - 519499137468236398662747. +-5160459932422355880342008555720285127460826532 = -9933529355932531354156 * 519499137468236398662747. +9933529355932531354156 = -(-9933529355932531354156). +-9933529355932531354156 = +(-9933529355932531354156). +0 = -9933529355932531354156 div 519499137468236398662747. +-9933529355932531354156 = -9933529355932531354156 rem 519499137468236398662747. +510015616812963311457360 = -9933529355932531354156 band 519499137468236398662747. +-450008700659444148769 = -9933529355932531354156 bor 519499137468236398662747. +-510465625513622755606129 = -9933529355932531354156 bxor 519499137468236398662747. +9933529355932531354155 = bnot(-9933529355932531354156). +-317872939389841003332992 = -9933529355932531354156 bsl 5. +-310422792372891604818 = -9933529355932531354156 bsr 5. +-37096154251521333714133 = 73423963737328583155 + -37169578215258662297288. +37243002178995990880443 = 73423963737328583155 - -37169578215258662297288. +-2729137763008950497871192185843978438983640 = 73423963737328583155 * -37169578215258662297288. +-73423963737328583155 = -(73423963737328583155). +73423963737328583155 = +(73423963737328583155). +0 = 73423963737328583155 div -37169578215258662297288. +73423963737328583155 = 73423963737328583155 rem -37169578215258662297288. +19055295172658069808 = 73423963737328583155 band -37169578215258662297288. +-37115209546693991783941 = 73423963737328583155 bor -37169578215258662297288. +-37134264841866649853749 = 73423963737328583155 bxor -37169578215258662297288. +-73423963737328583156 = bnot(73423963737328583155). +60086328323069571884886422554887049463830943694271535732589302468223369323657564870290153787226398591009460002240599573447008736990986904085469235396956305326233427640320 = 73423963737328583155 bsl 498. +0 = 73423963737328583155 bsr 498. +-97385435680005309784032198 = -31643372812742 + -97385435679973666411219456. +97385435679942023038406714 = -31643372812742 - -97385435679973666411219456. +3081603647752713441867279806232955108352 = -31643372812742 * -97385435679973666411219456. +31643372812742 = -(-31643372812742). +-31643372812742 = +(-31643372812742). +0 = -31643372812742 div -97385435679973666411219456. +-31643372812742 = -31643372812742 rem -97385435679973666411219456. +-97385435679987418936637952 = -31643372812742 band -97385435679973666411219456. +-17890847394246 = -31643372812742 bor -97385435679973666411219456. +97385435679969528089243706 = -31643372812742 bxor -97385435679973666411219456. +31643372812741 = bnot(-31643372812742). +-1 = -31643372812742 bsl -99. +-20056370269659015991794578266269362207850496 = -31643372812742 bsr -99. +2696944336321953535277237639 = 4 + 2696944336321953535277237635. +-2696944336321953535277237631 = 4 - 2696944336321953535277237635. +10787777345287814141108950540 = 4 * 2696944336321953535277237635. +-4 = -(4). +4 = +(4). +0 = 4 div 2696944336321953535277237635. +4 = 4 rem 2696944336321953535277237635. +0 = 4 band 2696944336321953535277237635. +2696944336321953535277237639 = 4 bor 2696944336321953535277237635. +2696944336321953535277237639 = 4 bxor 2696944336321953535277237635. +-5 = bnot(4). +68719476736 = 4 bsl 34. +0 = 4 bsr 34. +-4552277100 = -4453455525 + -98821575. +-4354633950 = -4453455525 - -98821575. +440097489172951875 = -4453455525 * -98821575. +4453455525 = -(-4453455525). +-4453455525 = +(-4453455525). +45 = -4453455525 div -98821575. +-6484650 = -4453455525 rem -98821575. +-4529059815 = -4453455525 band -98821575. +-23217285 = -4453455525 bor -98821575. +4505842530 = -4453455525 bxor -98821575. +4453455524 = bnot(-4453455525). +-1 = -4453455525 bsl -39. +-2448313066760385331200 = -4453455525 bsr -39. +9933367324985400417482 = -989164129354261 + 9933368314149529771743. +-9933369303313659126004 = -989164129354261 - 9933368314149529771743. +-9825731620020922984764659973314446923 = -989164129354261 * 9933368314149529771743. +989164129354261 = -(-989164129354261). +-989164129354261 = +(-989164129354261). +0 = -989164129354261 div 9933368314149529771743. +-989164129354261 = -989164129354261 rem 9933368314149529771743. +9933368032527978126539 = -989164129354261 band 9933368314149529771743. +-707542577709057 = -989164129354261 bor 9933368314149529771743. +-9933368740070555835596 = -989164129354261 bxor 9933368314149529771743. +989164129354260 = bnot(-989164129354261). +-1 = -989164129354261 bsl -816. +-432259772646768474565743340945911685180939112368269936973860870163212437849557138458245552085199626816186005750617365378632608731145945336023653710938459786500342977738666480323242539275941384501750417946839160709008859216903183353877678051450083859962208976896 = -989164129354261 bsr -816. +35455434641626474236 = -8191467337 + 35455434649817941573. +-35455434658009408910 = -8191467337 - 35455434649817941573. +-290432034853121701391803901101 = -8191467337 * 35455434649817941573. +8191467337 = -(-8191467337). +-8191467337 = +(-8191467337). +0 = -8191467337 div 35455434649817941573. +-8191467337 = -8191467337 rem 35455434649817941573. +35455434647532470277 = -8191467337 band 35455434649817941573. +-5905996041 = -8191467337 bor 35455434649817941573. +-35455434653438466318 = -8191467337 bxor 35455434649817941573. +8191467336 = bnot(-8191467337). +-4194031276544 = -8191467337 bsl 9. +-15998960 = -8191467337 bsr 9. +866121085978430578 = -6318836466295679 + 872439922444726257. +-878758758911021936 = -6318836466295679 - 872439922444726257. +-5512805196595910305947821976943503 = -6318836466295679 * 872439922444726257. +6318836466295679 = -(-6318836466295679). +-6318836466295679 = +(-6318836466295679). +0 = -6318836466295679 div 872439922444726257. +-6318836466295679 = -6318836466295679 rem 872439922444726257. +867370690654260353 = -6318836466295679 band 872439922444726257. +-1249604675829775 = -6318836466295679 bor 872439922444726257. +-868620295330090128 = -6318836466295679 bxor 872439922444726257. +6318836466295678 = bnot(-6318836466295679). +-1778594347189020103220526055424 = -6318836466295679 bsl 48. +-23 = -6318836466295679 bsr 48. +-838928431376113277356992188754 = 532 + -838928431376113277356992189286. +838928431376113277356992189818 = 532 - -838928431376113277356992189286. +-446309925492092263553919844700152 = 532 * -838928431376113277356992189286. +-532 = -(532). +532 = +(532). +0 = 532 div -838928431376113277356992189286. +532 = 532 rem -838928431376113277356992189286. +16 = 532 band -838928431376113277356992189286. +-838928431376113277356992188770 = 532 bor -838928431376113277356992189286. +-838928431376113277356992188786 = 532 bxor -838928431376113277356992189286. +-533 = bnot(532). +17024 = 532 bsl 5. +16 = 532 bsr 5. +835256139615651161826982037484 = 835256139615651258654646787165 + -96827664749681. +835256139615651355482311536846 = 835256139615651258654646787165 - -96827664749681. +-80875901466817027217390282385766390608644365 = 835256139615651258654646787165 * -96827664749681. +-835256139615651258654646787165 = -(835256139615651258654646787165). +835256139615651258654646787165 = +(835256139615651258654646787165). +-8626213817868648 = 835256139615651258654646787165 div -96827664749681. +12782788885877 = 835256139615651258654646787165 rem -96827664749681. +835256139615651240991861508109 = 835256139615651258654646787165 band -96827664749681. +-79164879470625 = 835256139615651258654646787165 bor -96827664749681. +-835256139615651320156740978734 = 835256139615651258654646787165 bxor -96827664749681. +-835256139615651258654646787166 = bnot(835256139615651258654646787165). +13050877181494550916478856049 = 835256139615651258654646787165 bsl -6. +53456392935401680553897394378560 = 835256139615651258654646787165 bsr -6. +5975929321496698341544 = 5975929321496698341539 + 5. +5975929321496698341534 = 5975929321496698341539 - 5. +29879646607483491707695 = 5975929321496698341539 * 5. +-5975929321496698341539 = -(5975929321496698341539). +5975929321496698341539 = +(5975929321496698341539). +1195185864299339668307 = 5975929321496698341539 div 5. +4 = 5975929321496698341539 rem 5. +1 = 5975929321496698341539 band 5. +5975929321496698341543 = 5975929321496698341539 bor 5. +5975929321496698341542 = 5975929321496698341539 bxor 5. +-5975929321496698341540 = bnot(5975929321496698341539). +371496063840359799118004057551362324785911970559740878742915756886585495727539355412378263482391299409051648 = 5975929321496698341539 bsl 285. +0 = 5975929321496698341539 bsr 285. +-76789134657341395858736391309 = 3 + -76789134657341395858736391312. +76789134657341395858736391315 = 3 - -76789134657341395858736391312. +-230367403972024187576209173936 = 3 * -76789134657341395858736391312. +-3 = -(3). +3 = +(3). +0 = 3 div -76789134657341395858736391312. +3 = 3 rem -76789134657341395858736391312. +0 = 3 band -76789134657341395858736391312. +-76789134657341395858736391309 = 3 bor -76789134657341395858736391312. +-76789134657341395858736391309 = 3 bxor -76789134657341395858736391312. +-4 = bnot(3). +96 = 3 bsl 5. +0 = 3 bsr 5. +-972912573952353043619267387590 = -972912571787978446351768634963 + -2164374597267498752627. +-972912569623603849084269882336 = -972912571787978446351768634963 - -2164374597267498752627. +2105747255740092318635706185048342783618905000297801 = -972912571787978446351768634963 * -2164374597267498752627. +972912571787978446351768634963 = -(-972912571787978446351768634963). +-972912571787978446351768634963 = +(-972912571787978446351768634963). +449512100 = -972912571787978446351768634963 div -2164374597267498752627. +-1383610820311025348263 = -972912571787978446351768634963 rem -2164374597267498752627. +-972912572697643119681296293491 = -972912571787978446351768634963 band -2164374597267498752627. +-1254709923937971094099 = -972912571787978446351768634963 bor -2164374597267498752627. +972912571442933195743325199392 = -972912571787978446351768634963 bxor -2164374597267498752627. +972912571787978446351768634962 = bnot(-972912571787978446351768634963). +-206022251 = -972912571787978446351768634963 bsl -72. +-4594449719774056986990108839949590416305948352053248 = -972912571787978446351768634963 bsr -72. +-368694148740671175525604 = 717324848622586465652 + -369411473589293761991256. +370128798437916348456908 = 717324848622586465652 - -369411473589293761991256. +-264988029371886745960981433433994966768338912 = 717324848622586465652 * -369411473589293761991256. +-717324848622586465652 = -(717324848622586465652). +717324848622586465652 = +(717324848622586465652). +0 = 717324848622586465652 div -369411473589293761991256. +717324848622586465652 = 717324848622586465652 rem -369411473589293761991256. +113049512052828540192 = 717324848622586465652 band -369411473589293761991256. +-368807198252724004065796 = 717324848622586465652 bor -369411473589293761991256. +-368920247764776832605988 = 717324848622586465652 bxor -369411473589293761991256. +-717324848622586465653 = bnot(717324848622586465652). +3255231258462683863258487392003512564171824532565768030597274640785308663687009408682524071334781070174200620562413181685430433235754844555593076739044560515618419345374711226882314266250976292724903960588751204902335018453221756485226777054353505364397985992256190606645305837000971566495144161050624 = 717324848622586465652 bsl 929. +0 = 717324848622586465652 bsr 929. +-836464698689084617970645316 = -836464698686742118695776464 + -2342499274868852. +-836464698684399619420907612 = -836464698686742118695776464 - -2342499274868852. +1959417950127086192853451457099349908299328 = -836464698686742118695776464 * -2342499274868852. +836464698686742118695776464 = -(-836464698686742118695776464). +-836464698686742118695776464 = +(-836464698686742118695776464). +357082159068 = -836464698686742118695776464 div -2342499274868852. +-1348053993226528 = -836464698686742118695776464 rem -2342499274868852. +-836464698686832487159265536 = -836464698686742118695776464 band -2342499274868852. +-2252130811379780 = -836464698686742118695776464 bor -2342499274868852. +836464698684580356347885756 = -836464698686742118695776464 bxor -2342499274868852. +836464698686742118695776463 = bnot(-836464698686742118695776464). +-6691717589493936949566211712 = -836464698686742118695776464 bsl 3. +-104558087335842764836972058 = -836464698686742118695776464 bsr 3. +696585230662675608544 = 726333654824223364519 + -29748424161547755975. +756082078985771120494 = 726333654824223364519 - -29748424161547755975. +-21607281646518214144391285666208885251025 = 726333654824223364519 * -29748424161547755975. +-726333654824223364519 = -(726333654824223364519). +726333654824223364519 = +(726333654824223364519). +-24 = 726333654824223364519 div -29748424161547755975. +12371474947077221119 = 726333654824223364519 rem -29748424161547755975. +705813141625409655841 = 726333654824223364519 band -29748424161547755975. +-9227910962734047297 = 726333654824223364519 bor -29748424161547755975. +-715041052588143703138 = 726333654824223364519 bxor -29748424161547755975. +-726333654824223364520 = bnot(726333654824223364519). +0 = 726333654824223364519 bsl -871. +11435690451366222024367175662929179710635743234945722592068379701662961338420744154925516990271411044523107699951959958023547144448199929569201741028579907058237786908876106979333458778292628538248539604428551721719270108790275745604896016465451216263949689199341385719758959895642112 = 726333654824223364519 bsr -871. +97526085963108 = 893141621 + 97525192821487. +-97524299679866 = 893141621 - 97525192821487. +87103808804920462810427 = 893141621 * 97525192821487. +-893141621 = -(893141621). +893141621 = +(893141621). +0 = 893141621 div 97525192821487. +893141621 = 893141621 rem 97525192821487. +272106085 = 893141621 band 97525192821487. +97525813857023 = 893141621 bor 97525192821487. +97525541750938 = 893141621 bxor 97525192821487. +-893141622 = bnot(893141621). +27910675 = 893141621 bsl -5. +28580531872 = 893141621 bsr -5. +-588282776776163612977818769727 = 6844 + -588282776776163612977818776571. +588282776776163612977818783415 = 6844 - -588282776776163612977818776571. +-4026207324256063767220191706851924 = 6844 * -588282776776163612977818776571. +-6844 = -(6844). +6844 = +(6844). +0 = 6844 div -588282776776163612977818776571. +6844 = 6844 rem -588282776776163612977818776571. +2052 = 6844 band -588282776776163612977818776571. +-588282776776163612977818771779 = 6844 bor -588282776776163612977818776571. +-588282776776163612977818773831 = 6844 bxor -588282776776163612977818776571. +-6845 = bnot(6844). +0 = 6844 bsl -79. +4136944154721261035844534272 = 6844 bsr -79. +5491768516893889754824 = 27265255183351 + 5491768489628634571473. +-5491768462363379388122 = 27265255183351 - 5491768489628634571473. +149734469277610821234926847929146023 = 27265255183351 * 5491768489628634571473. +-27265255183351 = -(27265255183351). +27265255183351 = +(27265255183351). +0 = 27265255183351 div 5491768489628634571473. +27265255183351 = 27265255183351 rem 5491768489628634571473. +9397493400273 = 27265255183351 band 5491768489628634571473. +5491768507496396354551 = 27265255183351 bor 5491768489628634571473. +5491768498098902954278 = 27265255183351 bxor 5491768489628634571473. +-27265255183352 = bnot(27265255183351). +590605833979279523757345160506562130760604478596484640331883899311197720867385191048344070202384917859514703010595620818844555467936296337408 = 27265255183351 bsl 423. +0 = 27265255183351 bsr 423. +-243633971503659577459246664 = 33528189219127257 + -243633971537187766678373921. +243633971570715955897501178 = 33528189219127257 - -243633971537187766678373921. +-8168605897906295864640451842147147529064697 = 33528189219127257 * -243633971537187766678373921. +-33528189219127257 = -(33528189219127257). +33528189219127257 = +(33528189219127257). +0 = 33528189219127257 div -243633971537187766678373921. +33528189219127257 = 33528189219127257 rem -243633971537187766678373921. +14378387645020633 = 33528189219127257 band -243633971537187766678373921. +-243633971518037965104267297 = 33528189219127257 bor -243633971537187766678373921. +-243633971532416352749287930 = 33528189219127257 bxor -243633971537187766678373921. +-33528189219127258 = bnot(33528189219127257). +65484744568607 = 33528189219127257 bsl -9. +17166432880193155584 = 33528189219127257 bsr -9. +-89954888350459534858325537 = -898356866157681 + -89954888349561177992167856. +89954888348662821126010175 = -898356866157681 - -89954888349561177992167856. +80811591593275869086159243769082315701936 = -898356866157681 * -89954888349561177992167856. +898356866157681 = -(-898356866157681). +-898356866157681 = +(-898356866157681). +0 = -898356866157681 div -89954888349561177992167856. +-898356866157681 = -898356866157681 rem -89954888349561177992167856. +-89954888349842704514911744 = -898356866157681 band -89954888349561177992167856. +-616830343413793 = -898356866157681 bor -89954888349561177992167856. +89954888349225874171497951 = -898356866157681 bxor -89954888349561177992167856. +898356866157680 = bnot(-898356866157681). +-56147304134856 = -898356866157681 bsl -4. +-14373709858522896 = -898356866157681 bsr -4. +64720118415810 = -75774795351 + 64795893211161. +-64871668006512 = -75774795351 - 64795893211161. +-4909895547660975004112511 = -75774795351 * 64795893211161. +75774795351 = -(-75774795351). +-75774795351 = +(-75774795351). +0 = -75774795351 div 64795893211161. +-75774795351 = -75774795351 rem 64795893211161. +64795356176393 = -75774795351 band 64795893211161. +-75237760583 = -75774795351 bor 64795893211161. +-64870593936976 = -75774795351 bxor 64795893211161. +75774795350 = bnot(-75774795351). +-18943698838 = -75774795351 bsl -2. +-303099181404 = -75774795351 bsr -2. +-31142252253840804847011712537 = -31142252253756192995144998645 + -84611851866713892. +-31142252253671581143278284753 = -31142252253756192995144998645 - -84611851866713892. +2635003634490655848531253998671200774942676340 = -31142252253756192995144998645 * -84611851866713892. +31142252253756192995144998645 = -(-31142252253756192995144998645). +-31142252253756192995144998645 = +(-31142252253756192995144998645). +368060166119 = -31142252253756192995144998645 div -84611851866713892. +-57257658979973497 = -31142252253756192995144998645 rem -84611851866713892. +-31142252253765340962695790584 = -31142252253756192995144998645 band -84611851866713892. +-75463884315921953 = -31142252253756192995144998645 bor -84611851866713892. +31142252253689877078379868631 = -31142252253756192995144998645 bxor -84611851866713892. +31142252253756192995144998644 = bnot(-31142252253756192995144998645). +-6441 = -31142252253756192995144998645 bsl -82. +-150594691322070952976781795744798420507787935172526080 = -31142252253756192995144998645 bsr -82. +-768279695054038550429476 = -57614822655244 + -768279694996423727774232. +768279694938808905118988 = -57614822655244 - -768279694996423727774232. +44264298376843904180525501948402872608 = -57614822655244 * -768279694996423727774232. +57614822655244 = -(-57614822655244). +-57614822655244 = +(-57614822655244). +0 = -57614822655244 div -768279694996423727774232. +-57614822655244 = -57614822655244 rem -768279694996423727774232. +-768279695049200370319136 = -57614822655244 band -768279694996423727774232. +-4838180110340 = -57614822655244 bor -768279694996423727774232. +768279695044362190208796 = -57614822655244 bxor -768279694996423727774232. +57614822655243 = bnot(-57614822655244). +-7201852831906 = -57614822655244 bsl -3. +-460918581241952 = -57614822655244 bsr -3. +66716996688288331280347926915 = 78862962169674868952653347 + 66638133726118656411395273568. +-66559270763948981542442620221 = 78862962169674868952653347 - 66638133726118656411395273568. +5255280619100630615291494137334154503933005328535832096 = 78862962169674868952653347 * 66638133726118656411395273568. +-78862962169674868952653347 = -(78862962169674868952653347). +78862962169674868952653347 = +(78862962169674868952653347). +0 = 78862962169674868952653347 div 66638133726118656411395273568. +78862962169674868952653347 = 78862962169674868952653347 rem 66638133726118656411395273568. +78587880854205447134089760 = 78862962169674868952653347 band 66638133726118656411395273568. +66638408807434125833213837155 = 78862962169674868952653347 bor 66638133726118656411395273568. +66559820926579920386079747395 = 78862962169674868952653347 bxor 66638133726118656411395273568. +-78862962169674868952653348 = bnot(78862962169674868952653347). +5047229578859191612969814208 = 78862962169674868952653347 bsl 6. +1232233783901169827385208 = 78862962169674868952653347 bsr 6. +363496995691681518346351 = 76 + 363496995691681518346275. +-363496995691681518346199 = 76 - 363496995691681518346275. +27625771672567795394316900 = 76 * 363496995691681518346275. +-76 = -(76). +76 = +(76). +0 = 76 div 363496995691681518346275. +76 = 76 rem 363496995691681518346275. +0 = 76 band 363496995691681518346275. +363496995691681518346351 = 76 bor 363496995691681518346275. +363496995691681518346351 = 76 bxor 363496995691681518346275. +-77 = bnot(76). +21392098230009856 = 76 bsl 48. +0 = 76 bsr 48. +45388257267872619604708117937 = 45388257267875444867293787589 + -2825262585669652. +45388257267878270129879457241 = 45388257267875444867293787589 - -2825262585669652. +-128233745087677154079742755684412077011549028 = 45388257267875444867293787589 * -2825262585669652. +-45388257267875444867293787589 = -(45388257267875444867293787589). +45388257267875444867293787589 = +(45388257267875444867293787589). +-16065146474559 = 45388257267875444867293787589 div -2825262585669652. +1190325297404121 = 45388257267875444867293787589 rem -2825262585669652. +45388257267875436034622232004 = 45388257267875444867293787589 band -2825262585669652. +-2816429914114067 = 45388257267875444867293787589 bor -2825262585669652. +-45388257267878252464536346071 = 45388257267875444867293787589 bxor -2825262585669652. +-45388257267875444867293787590 = bnot(45388257267875444867293787589). +181553029071501779469175150356 = 45388257267875444867293787589 bsl 2. +11347064316968861216823446897 = 45388257267875444867293787589 bsr 2. +534232775221076557060361434224 = 8142637292681815651 + 534232775212933919767679618573. +-534232775204791282474997802922 = 8142637292681815651 - 534232775212933919767679618573. +4350063718421737243249387242627227872212781686023 = 8142637292681815651 * 534232775212933919767679618573. +-8142637292681815651 = -(8142637292681815651). +8142637292681815651 = +(8142637292681815651). +0 = 8142637292681815651 div 534232775212933919767679618573. +8142637292681815651 = 8142637292681815651 rem 534232775212933919767679618573. +8070450807195059713 = 8142637292681815651 band 534232775212933919767679618573. +534232775213006106253166374511 = 8142637292681815651 bor 534232775212933919767679618573. +534232775204935655445971314798 = 8142637292681815651 bxor 534232775212933919767679618573. +-8142637292681815652 = bnot(8142637292681815651). +254457415396306739 = 8142637292681815651 bsl -5. +260564393365818100832 = 8142637292681815651 bsr -5. +-719 = 5 + -724. +729 = 5 - -724. +-3620 = 5 * -724. +-5 = -(5). +5 = +(5). +0 = 5 div -724. +5 = 5 rem -724. +4 = 5 band -724. +-723 = 5 bor -724. +-727 = 5 bxor -724. +-6 = bnot(5). +80 = 5 bsl 4. +0 = 5 bsr 4. +-33698381775178712848228269225 = 6383716279392 + -33698381775178719231944548617. +33698381775178725615660828009 = 6383716279392 - -33698381775178719231944548617. +-215120908327375073751204849770572099200864 = 6383716279392 * -33698381775178719231944548617. +-6383716279392 = -(6383716279392). +6383716279392 = +(6383716279392). +0 = 6383716279392 div -33698381775178719231944548617. +6383716279392 = 6383716279392 rem -33698381775178719231944548617. +5008250897504 = 6383716279392 band -33698381775178719231944548617. +-33698381775178717856479166729 = 6383716279392 bor -33698381775178719231944548617. +-33698381775178722864730064233 = 6383716279392 bxor -33698381775178719231944548617. +-6383716279393 = bnot(6383716279392). +24936391716 = 6383716279392 bsl -8. +1634231367524352 = 6383716279392 bsr -8. +473371560325055 = -59763632186814 + 533135192511869. +-592898824698683 = -59763632186814 - 533135192511869. +-31862095551125612402120295366 = -59763632186814 * 533135192511869. +59763632186814 = -(-59763632186814). +-59763632186814 = +(-59763632186814). +0 = -59763632186814 div 533135192511869. +-59763632186814 = -59763632186814 rem 533135192511869. +493269238960192 = -59763632186814 band 533135192511869. +-19897678635137 = -59763632186814 bor 533135192511869. +-513166917595329 = -59763632186814 bxor 533135192511869. +59763632186813 = bnot(-59763632186814). +-13915 = -59763632186814 bsl -32. +-256682845732539092434944 = -59763632186814 bsr -32. +9147059083566908696 = 8353389925127187513 + 793669158439721183. +7559720766687466330 = 8353389925127187513 - 793669158439721183. +6629827951994540456288032372679187879 = 8353389925127187513 * 793669158439721183. +-8353389925127187513 = -(8353389925127187513). +8353389925127187513 = +(8353389925127187513). +10 = 8353389925127187513 div 793669158439721183. +416698340729975683 = 8353389925127187513 rem 793669158439721183. +216491503072577561 = 8353389925127187513 band 793669158439721183. +8930567580494331135 = 8353389925127187513 bor 793669158439721183. +8714076077421753574 = 8353389925127187513 bxor 793669158439721183. +-8353389925127187514 = bnot(8353389925127187513). +2138467820832560003328 = 8353389925127187513 bsl 8. +32630429395028076 = 8353389925127187513 bsr 8. +72362913728339258532 = 72362913728339235883 + 22649. +72362913728339213234 = 72362913728339235883 - 22649. +1638947633033155353514067 = 72362913728339235883 * 22649. +-72362913728339235883 = -(72362913728339235883). +72362913728339235883 = +(72362913728339235883). +3194971686535354 = 72362913728339235883 div 22649. +3137 = 72362913728339235883 rem 22649. +20521 = 72362913728339235883 band 22649. +72362913728339238011 = 72362913728339235883 bor 22649. +72362913728339217490 = 72362913728339235883 bxor 22649. +-72362913728339235884 = bnot(72362913728339235883). +4016 = 72362913728339235883 bsl -54. +1303574365209567728547354356714831872 = 72362913728339235883 bsr -54. +17436186965801552151 = 7797441669221589463 + 9638745296579962688. +-1841303627358373225 = 7797441669221589463 - 9638745296579962688. +75157554214566208648139375940593956544 = 7797441669221589463 * 9638745296579962688. +-7797441669221589463 = -(7797441669221589463). +7797441669221589463 = +(7797441669221589463). +0 = 7797441669221589463 div 9638745296579962688. +7797441669221589463 = 7797441669221589463 rem 9638745296579962688. +288815050620674368 = 7797441669221589463 band 9638745296579962688. +17147371915180877783 = 7797441669221589463 bor 9638745296579962688. +16858556864560203415 = 7797441669221589463 bxor 9638745296579962688. +-7797441669221589464 = bnot(7797441669221589463). +15229378260198416 = 7797441669221589463 bsl -9. +3992290134641453805056 = 7797441669221589463 bsr -9. +-249371619938137286729145349434 = 55186244262 + -249371619938137286784331593696. +249371619938137286839517837958 = 55186244262 - -249371619938137286784331593696. +-13761883129916673637770067844111195372352 = 55186244262 * -249371619938137286784331593696. +-55186244262 = -(55186244262). +55186244262 = +(55186244262). +0 = 55186244262 div -249371619938137286784331593696. +55186244262 = 55186244262 rem -249371619938137286784331593696. +21184544 = 55186244262 band -249371619938137286784331593696. +-249371619938137286729166533978 = 55186244262 bor -249371619938137286784331593696. +-249371619938137286729187718522 = 55186244262 bxor -249371619938137286784331593696. +-55186244263 = bnot(55186244262). +428834400026232149395182982878267995633372152430042768694025038616215998110292595899915669864448 = 55186244262 bsl 282. +0 = 55186244262 bsr 282. +-31637674 = -31637667 + -7. +-31637660 = -31637667 - -7. +221463669 = -31637667 * -7. +31637667 = -(-31637667). +-31637667 = +(-31637667). +4519666 = -31637667 div -7. +-5 = -31637667 rem -7. +-31637671 = -31637667 band -7. +-3 = -31637667 bor -7. +31637668 = -31637667 bxor -7. +31637666 = bnot(-31637667). +-8696495685551259648 = -31637667 bsl 38. +-1 = -31637667 bsr 38. +34884055521500638 = 34883342235339514 + 713286161124. +34882628949178390 = 34883342235339514 - 713286161124. +24881805270220014909847853736 = 34883342235339514 * 713286161124. +-34883342235339514 = -(34883342235339514). +34883342235339514 = +(34883342235339514). +48905 = 34883342235339514 div 713286161124. +82525570294 = 34883342235339514 rem 713286161124. +163242312416 = 34883342235339514 band 713286161124. +34883892279188222 = 34883342235339514 bor 713286161124. +34883729036875806 = 34883342235339514 bxor 713286161124. +-34883342235339515 = bnot(34883342235339514). +558133475765432224 = 34883342235339514 bsl 4. +2180208889708719 = 34883342235339514 bsr 4. +-56817515656656 = 541178 + -56817516197834. +56817516739012 = 541178 - -56817516197834. +-30748389780911408452 = 541178 * -56817516197834. +-541178 = -(541178). +541178 = +(541178). +0 = 541178 div -56817516197834. +541178 = 541178 rem -56817516197834. +16434 = 541178 band -56817516197834. +-56817515673090 = 541178 bor -56817516197834. +-56817515689524 = 541178 bxor -56817516197834. +-541179 = bnot(541178). +4874498078282220568576 = 541178 bsl 53. +0 = 541178 bsr 53. +5517514786496594214410504 = 618239 + 5517514786496594213792265. +-5517514786496594213174026 = 618239 - 5517514786496594213792265. +3411142824088867910140716121335 = 618239 * 5517514786496594213792265. +-618239 = -(618239). +618239 = +(618239). +0 = 618239 div 5517514786496594213792265. +618239 = 618239 rem 5517514786496594213792265. +27145 = 618239 band 5517514786496594213792265. +5517514786496594214383359 = 618239 bor 5517514786496594213792265. +5517514786496594214356214 = 618239 bxor 5517514786496594213792265. +-618240 = bnot(618239). +9891824 = 618239 bsl 4. +38639 = 618239 bsr 4. +528252633090290629 = 5869819193392718 + 522382813896897911. +-516512994703505193 = 5869819193392718 - 522382813896897911. +3066292667310507615057367776812098 = 5869819193392718 * 522382813896897911. +-5869819193392718 = -(5869819193392718). +5869819193392718 = +(5869819193392718). +0 = 5869819193392718 div 522382813896897911. +5869819193392718 = 5869819193392718 rem 522382813896897911. +5840609038496838 = 5869819193392718 band 522382813896897911. +522412024051793791 = 5869819193392718 bor 522382813896897911. +516571415013296953 = 5869819193392718 bxor 522382813896897911. +-5869819193392719 = bnot(5869819193392718). +93917107094283488 = 5869819193392718 bsl 4. +366863699587044 = 5869819193392718 bsr 4. +93451451842942818555 = -855656892 + 93451451843798475447. +-93451451844654132339 = -855656892 - 93451451843798475447. +-79962378837552272975318330724 = -855656892 * 93451451843798475447. +855656892 = -(-855656892). +-855656892 = +(-855656892). +0 = -855656892 div 93451451843798475447. +-855656892 = -855656892 rem 93451451843798475447. +93451451843228049924 = -855656892 band 93451451843798475447. +-285231369 = -855656892 bor 93451451843798475447. +-93451451843513281293 = -855656892 bxor 93451451843798475447. +855656891 = bnot(-855656892). +-1 = -855656892 bsl -986. +-559596999863434058181088787703630780480556894737428043058390821616679397799374967206458383762742284413287718056878721836706115755314903261006719275360075705173593849705167073442107788566149655603624348072477881781982878106212705711322388638085309768430813689625159547205033343575193347563752997552796991488 = -855656892 bsr -986. +447649719154665546776115 = 447649719154622935599339 + 42611176776. +447649719154580324422563 = 447649719154622935599339 - 42611176776. +19074881316624391186447497637751064 = 447649719154622935599339 * 42611176776. +-447649719154622935599339 = -(447649719154622935599339). +447649719154622935599339 = +(447649719154622935599339). +10505453099965 = 447649719154622935599339 div 42611176776. +37121186499 = 447649719154622935599339 rem 42611176776. +3229614152 = 447649719154622935599339 band 42611176776. +447649719154662317161963 = 447649719154622935599339 bor 42611176776. +447649719154659087547811 = 447649719154622935599339 bxor 42611176776. +-447649719154622935599340 = bnot(447649719154622935599339). +3497263430895491684369 = 447649719154622935599339 bsl -7. +57299164051791735756715392 = 447649719154622935599339 bsr -7. +-526687489683481433080338 = -526687489683481428111489 + -4968849. +-526687489683481423142640 = -526687489683481428111489 - -4968849. +2617030606426277010590344006161 = -526687489683481428111489 * -4968849. +526687489683481428111489 = -(-526687489683481428111489). +-526687489683481428111489 = +(-526687489683481428111489). +105997885965840666 = -526687489683481428111489 div -4968849. +-698055 = -526687489683481428111489 rem -4968849. +-526687489683481432945041 = -526687489683481428111489 band -4968849. +-135297 = -526687489683481428111489 bor -4968849. +526687489683481432809744 = -526687489683481428111489 bxor -4968849. +526687489683481428111488 = bnot(-526687489683481428111489). +-1962063795639133 = -526687489683481428111489 bsl -28. +-141381596462680632822638768553984 = -526687489683481428111489 bsr -28. +-768406856353371 = -36812223784429 + -731594632568942. +694782408784513 = -36812223784429 - -731594632568942. +26931625333615001809488604118 = -36812223784429 * -731594632568942. +36812223784429 = -(-36812223784429). +-36812223784429 = +(-36812223784429). +0 = -36812223784429 div -731594632568942. +-36812223784429 = -36812223784429 rem -731594632568942. +-766890699236846 = -36812223784429 band -731594632568942. +-1516157116525 = -36812223784429 bor -731594632568942. +765374542120321 = -36812223784429 bxor -731594632568942. +36812223784428 = bnot(-36812223784429). +-5696415719734780799497428387179383488512 = -36812223784429 bsl 87. +-1 = -36812223784429 bsr 87. +-6156884284911674685174760725 = 7738353147 + -6156884284911674692913113872. +6156884284911674700651467019 = 7738353147 - -6156884284911674692913113872. +-47644144881861102476944453328960555184 = 7738353147 * -6156884284911674692913113872. +-7738353147 = -(7738353147). +7738353147 = +(7738353147). +0 = 7738353147 div -6156884284911674692913113872. +7738353147 = 7738353147 rem -6156884284911674692913113872. +1073825008 = 7738353147 band -6156884284911674692913113872. +-6156884284911674686248585733 = 7738353147 bor -6156884284911674692913113872. +-6156884284911674687322410741 = 7738353147 bxor -6156884284911674692913113872. +-7738353148 = bnot(7738353147). +0 = 7738353147 bsl -49. +4356305543661313132068864 = 7738353147 bsr -49. +-9331217104250 = -6857773436789 + -2473443667461. +-4384329769328 = -6857773436789 - -2473443667461. +16962316280108010419622729 = -6857773436789 * -2473443667461. +6857773436789 = -(-6857773436789). +-6857773436789 = +(-6857773436789). +2 = -6857773436789 div -2473443667461. +-1910886101867 = -6857773436789 rem -2473443667461. +-6871809224565 = -6857773436789 band -2473443667461. +-2459407879685 = -6857773436789 bor -2473443667461. +4412401344880 = -6857773436789 bxor -2473443667461. +6857773436788 = bnot(-6857773436789). +-1 = -6857773436789 bsl -711. +-73877135891535041194567845409532392555449692441996201171567393259263971087275630149583954972045843046579819926045499081403789204710777913948952840714061305344623347040087488483321504037757473989273894688863749707071200136527872 = -6857773436789 bsr -711. +-8862 = -3163 + -5699. +2536 = -3163 - -5699. +18025937 = -3163 * -5699. +3163 = -(-3163). +-3163 = +(-3163). +0 = -3163 div -5699. +-3163 = -3163 rem -5699. +-7771 = -3163 band -5699. +-1091 = -3163 bor -5699. +6680 = -3163 bxor -5699. +3162 = bnot(-3163). +-7747583955804587064033025409816693034551909564216481017690646693299710659329624213439192275631247214614854720650283481286037929452644368456245063859770027514737272854791614349968839653855242186565464621056 = -3163 bsl 669. +-1 = -3163 bsr 669. +49938691529915359744835 = 673513368 + 49938691529914686231467. +-49938691529914012718099 = 673513368 - 49938691529914686231467. +33634376325825913076418566750856 = 673513368 * 49938691529914686231467. +-673513368 = -(673513368). +673513368 = +(673513368). +0 = 673513368 div 49938691529914686231467. +673513368 = 673513368 rem 49938691529914686231467. +2413448 = 673513368 band 49938691529914686231467. +49938691529915357331387 = 673513368 bor 49938691529914686231467. +49938691529915354917939 = 673513368 bxor 49938691529914686231467. +-673513369 = bnot(673513368). +40 = 673513368 bsl -24. +11299679253823488 = 673513368 bsr -24. +-3778957544766119360 = -3778956672496357543 + -872269761817. +-3778955800226595726 = -3778956672496357543 - -872269761817. +3296269636635160668832681335631 = -3778956672496357543 * -872269761817. +3778956672496357543 = -(-3778956672496357543). +-3778956672496357543 = +(-3778956672496357543). +4332325 = -3778956672496357543 div -872269761817. +-576632523018 = -3778956672496357543 rem -872269761817. +-3778957536090971583 = -3778956672496357543 band -872269761817. +-8675147777 = -3778956672496357543 bor -872269761817. +3778957527415823806 = -3778956672496357543 bxor -872269761817. +3778956672496357542 = bnot(-3778956672496357543). +-1 = -3778956672496357543 bsl -574. +-233662717739497829481445250147111709136982365013769391462699314908304472573989039157320248745318224210099370341970651220915547562381773285418885296295503586503787527171820935607181131447795712 = -3778956672496357543 bsr -574. +-649232869612948879619714134339 = -725 + -649232869612948879619714133614. +649232869612948879619714132889 = -725 - -649232869612948879619714133614. +470693830469387937724292746870150 = -725 * -649232869612948879619714133614. +725 = -(-725). +-725 = +(-725). +0 = -725 div -649232869612948879619714133614. +-725 = -725 rem -649232869612948879619714133614. +-649232869612948879619714133758 = -725 band -649232869612948879619714133614. +-581 = -725 bor -649232869612948879619714133614. +649232869612948879619714133177 = -725 bxor -649232869612948879619714133614. +724 = bnot(-725). +-182 = -725 bsl -2. +-2900 = -725 bsr -2. +336153821221413443388253589123 = 336153821221413443388254443641 + -854518. +336153821221413443388255298159 = 336153821221413443388254443641 - -854518. +-287249491002479772817244410671220038 = 336153821221413443388254443641 * -854518. +-336153821221413443388254443641 = -(336153821221413443388254443641). +336153821221413443388254443641 = +(336153821221413443388254443641). +-393384131430131891181056 = 336153821221413443388254443641 div -854518. +832633 = 336153821221413443388254443641 rem -854518. +336153821221413443388254113800 = 336153821221413443388254443641 band -854518. +-524677 = 336153821221413443388254443641 bor -854518. +-336153821221413443388254638477 = 336153821221413443388254443641 bxor -854518. +-336153821221413443388254443642 = bnot(336153821221413443388254443641). +0 = 336153821221413443388254443641 bsl -859. +1292124400582025214681753805379999017826458544223285740214950304716425204700493732921339170721971191611095287667243285143016059894708138089168312449178554746377958816494701003039401515512800135243884361346414364814334839205381088559598646160649881162109023652744982065088981627652232183808 = 336153821221413443388254443641 bsr -859. +-48828401135 = -2461564478 + -46366836657. +43905272179 = -2461564478 - -46366836657. +114134958072099470046 = -2461564478 * -46366836657. +2461564478 = -(-2461564478). +-2461564478 = +(-2461564478). +0 = -2461564478 div -46366836657. +-2461564478 = -2461564478 rem -46366836657. +-46636335038 = -2461564478 band -46366836657. +-2192066097 = -2461564478 bor -46366836657. +44444268941 = -2461564478 bxor -46366836657. +2461564477 = bnot(-2461564478). +-1 = -2461564478 bsl -78. +-743962213525101706399794732204032 = -2461564478 bsr -78. +-556775059482823128027518 = -556778541154981477947271 + 3481672158349919753. +-556782022827139827867024 = -556778541154981477947271 - 3481672158349919753. +-1938520345105983984371355886263702015344063 = -556778541154981477947271 * 3481672158349919753. +556778541154981477947271 = -(-556778541154981477947271). +-556778541154981477947271 = +(-556778541154981477947271). +-159916 = -556778541154981477947271 div 3481672158349919753. +-3456280295710726523 = -556778541154981477947271 rem 3481672158349919753. +3458837223825244169 = -556778541154981477947271 band 3481672158349919753. +-556778518320046953271687 = -556778541154981477947271 bor 3481672158349919753. +-556781977157270778515856 = -556778541154981477947271 bxor 3481672158349919753. +556778541154981477947270 = bnot(-556778541154981477947271). +-4349832352773292796464 = -556778541154981477947271 bsl -7. +-71267653267837629177250688 = -556778541154981477947271 bsr -7. +-97754190262650772370872987 = -98197617887185616669216942 + 443427624534844298343955. +-98641045511720460967560897 = -98197617887185616669216942 - 443427624534844298343955. +-43543536434695054084525258535137170335157229285610 = -98197617887185616669216942 * 443427624534844298343955. +98197617887185616669216942 = -(-98197617887185616669216942). +-98197617887185616669216942 = +(-98197617887185616669216942). +-221 = -98197617887185616669216942 div 443427624534844298343955. +-200112864985026735202887 = -98197617887185616669216942 rem 443427624534844298343955. +329389834326850956174866 = -98197617887185616669216942 band 443427624534844298343955. +-98083580096977623327047853 = -98197617887185616669216942 bor 443427624534844298343955. +-98412969931304474283222719 = -98197617887185616669216942 bxor 443427624534844298343955. +98197617887185616669216941 = bnot(-98197617887185616669216942). +-383584444871818815114129 = -98197617887185616669216942 bsl -8. +-25138590179119517867319537152 = -98197617887185616669216942 bsr -8. +65325146671884263620246 = -2375599319477 + 65325146674259862939723. +-65325146676635462259200 = -2375599319477 - 65325146674259862939723. +-155186373984106940192261251470884871 = -2375599319477 * 65325146674259862939723. +2375599319477 = -(-2375599319477). +-2375599319477 = +(-2375599319477). +0 = -2375599319477 div 65325146674259862939723. +-2375599319477 = -2375599319477 rem 65325146674259862939723. +65325146674255093956683 = -2375599319477 band 65325146674259862939723. +-2370830336437 = -2375599319477 bor 65325146674259862939723. +-65325146676625924293120 = -2375599319477 bxor 65325146674259862939723. +2375599319476 = bnot(-2375599319477). +-38009589111632 = -2375599319477 bsl 4. +-148474957468 = -2375599319477 bsr 4. +524147523146881815581505024662 = 524147523146881815517932188839 + 63572835823. +524147523146881815454359353016 = 524147523146881815517932188839 - 63572835823. +33321544436048809972305676753508779979497 = 524147523146881815517932188839 * 63572835823. +-524147523146881815517932188839 = -(524147523146881815517932188839). +524147523146881815517932188839 = +(524147523146881815517932188839). +8244834705914607277 = 524147523146881815517932188839 div 63572835823. +39690104868 = 524147523146881815517932188839 rem 63572835823. +51676738727 = 524147523146881815517932188839 band 63572835823. +524147523146881815529828285935 = 524147523146881815517932188839 bor 63572835823. +524147523146881815478151547208 = 524147523146881815517932188839 bxor 63572835823. +-524147523146881815517932188840 = bnot(524147523146881815517932188839). +110992555 = 524147523146881815517932188839 bsl -72. +2475216695387976233192489581374336681680929181138944 = 524147523146881815517932188839 bsr -72. +788157169335553457993544312218 = 788157169335553457992572592346 + 971719872. +788157169335553457991600872474 = 788157169335553457992572592346 - 971719872. +765867983702626331249700016385163299712 = 788157169335553457992572592346 * 971719872. +-788157169335553457992572592346 = -(788157169335553457992572592346). +788157169335553457992572592346 = +(788157169335553457992572592346). +811095040912730719571 = 788157169335553457992572592346 div 971719872. +572577434 = 788157169335553457992572592346 rem 971719872. +30097600 = 788157169335553457992572592346 band 971719872. +788157169335553457993514214618 = 788157169335553457992572592346 bor 971719872. +788157169335553457993484117018 = 788157169335553457992572592346 bxor 971719872. +-788157169335553457992572592347 = bnot(788157169335553457992572592346). +0 = 788157169335553457992572592346 bsl -945. +234400607467991052780843019870991817329861630439057960281722580280810231453180252492156694352398844086727915063510342812594864041835995223590154472972256657500844954457923059382361422736857621154335734662262532892155554792243506175409804520676108851065559235441081280792496342485860126981192353512187823008484687872 = 788157169335553457992572592346 bsr -945. +456498221969429928 = 45395 + 456498221969384533. +-456498221969339138 = 45395 - 456498221969384533. +20722736786300210875535 = 45395 * 456498221969384533. +-45395 = -(45395). +45395 = +(45395). +0 = 45395 div 456498221969384533. +45395 = 45395 rem 456498221969384533. +8273 = 45395 band 456498221969384533. +456498221969421655 = 45395 bor 456498221969384533. +456498221969413382 = 45395 bxor 456498221969384533. +-45396 = bnot(45395). +0 = 45395 bsl -65. +1674779894452090191216640 = 45395 bsr -65. +58272100780201 = 5813589616752 + 52458511163449. +-46644921546697 = 5813589616752 - 52458511163449. +304972255810095985540497648 = 5813589616752 * 52458511163449. +-5813589616752 = -(5813589616752). +5813589616752 = +(5813589616752). +0 = 5813589616752 div 52458511163449. +5813589616752 = 5813589616752 rem 52458511163449. +5504283713584 = 5813589616752 band 52458511163449. +52767817066617 = 5813589616752 bor 52458511163449. +47263533353033 = 5813589616752 bxor 52458511163449. +-5813589616753 = bnot(5813589616752). +0 = 5813589616752 bsl -249. +5259122560094394097887193586280664621930222978143017527786994756394715120927690796826624 = 5813589616752 bsr -249. +-811217921544075522 = 22713615154896373 + -833931536698971895. +856645151853868268 = 22713615154896373 - -833931536698971895. +-18941599990111788883837564364436835 = 22713615154896373 * -833931536698971895. +-22713615154896373 = -(22713615154896373). +22713615154896373 = +(22713615154896373). +0 = 22713615154896373 div -833931536698971895. +22713615154896373 = 22713615154896373 rem -833931536698971895. +18016226019068161 = 22713615154896373 band -833931536698971895. +-829234147563143683 = 22713615154896373 bor -833931536698971895. +-847250373582211844 = 22713615154896373 bxor -833931536698971895. +-22713615154896374 = bnot(22713615154896373). +363417842478341968 = 22713615154896373 bsl 4. +1419600947181023 = 22713615154896373 bsr 4. +5456 = -66 + 5522. +-5588 = -66 - 5522. +-364452 = -66 * 5522. +66 = -(-66). +-66 = +(-66). +0 = -66 div 5522. +-66 = -66 rem 5522. +5522 = -66 band 5522. +-66 = -66 bor 5522. +-5588 = -66 bxor 5522. +65 = bnot(-66). +-1 = -66 bsl -861. +-1014776034715873720684741443386595231429787920740899294045678304850603383056116311499835541721706232086537349665158267971309685931982741617205773147828702700672249808672767119573437380797816007092467025269927062172028523267991930326776759329910401937327974776832 = -66 bsr -861. +5196785811345279665568573520 = 75194 + 5196785811345279665568498326. +-5196785811345279665568423132 = 75194 - 5196785811345279665568498326. +390767112298296959172757663125244 = 75194 * 5196785811345279665568498326. +-75194 = -(75194). +75194 = +(75194). +0 = 75194 div 5196785811345279665568498326. +75194 = 75194 rem 5196785811345279665568498326. +146 = 75194 band 5196785811345279665568498326. +5196785811345279665568573374 = 75194 bor 5196785811345279665568498326. +5196785811345279665568573228 = 75194 bxor 5196785811345279665568498326. +-75195 = bnot(75194). +0 = 75194 bsl -49. +42330458797562134528 = 75194 bsr -49. +-527576 = 3536 + -531112. +534648 = 3536 - -531112. +-1878012032 = 3536 * -531112. +-3536 = -(3536). +3536 = +(3536). +0 = 3536 div -531112. +3536 = 3536 rem -531112. +1360 = 3536 band -531112. +-528936 = 3536 bor -531112. +-530296 = 3536 bxor -531112. +-3537 = bnot(3536). +0 = 3536 bsl -523. +97095698104887343808704004902207225665058892885226911710475291166720322785976447201221483557515613225598879028321105256077053398267992210085047056149531368357888 = 3536 bsr -523. +194861382607051816055649501 = 8184173239335391298581224112 + -7989311856728339482525574611. +16173485096063730781106798723 = 8184173239335391298581224112 - -7989311856728339482525574611. +-65385912298541023764191404366290936156944601698568220432 = 8184173239335391298581224112 * -7989311856728339482525574611. +-8184173239335391298581224112 = -(8184173239335391298581224112). +8184173239335391298581224112 = +(8184173239335391298581224112). +-1 = 8184173239335391298581224112 div -7989311856728339482525574611. +194861382607051816055649501 = 8184173239335391298581224112 rem -7989311856728339482525574611. +659166956033658411882699296 = 8184173239335391298581224112 band -7989311856728339482525574611. +-464305573426606595827049795 = 8184173239335391298581224112 bor -7989311856728339482525574611. +-1123472529460265007709749091 = 8184173239335391298581224112 bxor -7989311856728339482525574611. +-8184173239335391298581224113 = bnot(8184173239335391298581224112). +0 = 8184173239335391298581224112 bsl -848. +15360704581040881949470074138553440868943889412111113776588868549988553860433207151006860525408649511176731212529971171670484927035841364300665867032458282255893662134560851235709044534840334938773177773825554117097592516116215828036110551084445750840532370878910844498230861965033472 = 8184173239335391298581224112 bsr -848. +-24469893012618 = -24469883178955 + -9833663. +-24469873345292 = -24469883178955 - -9833663. +240628584831212162165 = -24469883178955 * -9833663. +24469883178955 = -(-24469883178955). +-24469883178955 = +(-24469883178955). +2488379 = -24469883178955 div -9833663. +-2676678 = -24469883178955 rem -9833663. +-24469883572223 = -24469883178955 band -9833663. +-9440395 = -24469883178955 bor -9833663. +24469874131828 = -24469883178955 bxor -9833663. +24469883178954 = bnot(-24469883178955). +-3388815562760659540322787124611722074864605117165619288748126783639116305815276462163657745235017088176590901286599153079163310119519980301350579944449075884550540718729845948037455500638928402240973972195935287936127385696634369984694284188180163816400164604802252283180697041035298078720 = -24469883178955 bsl 914. +-1 = -24469883178955 bsr 914. +2929337694275698696311920100 = 2929337694275698696311924425 + -4325. +2929337694275698696311928750 = 2929337694275698696311924425 - -4325. +-12669385527742396861549073138125 = 2929337694275698696311924425 * -4325. +-2929337694275698696311924425 = -(2929337694275698696311924425). +2929337694275698696311924425 = +(2929337694275698696311924425). +-677303513127329178338017 = 2929337694275698696311924425 div -4325. +900 = 2929337694275698696311924425 rem -4325. +2929337694275698696311924233 = 2929337694275698696311924425 band -4325. +-4133 = 2929337694275698696311924425 bor -4325. +-2929337694275698696311928366 = 2929337694275698696311924425 bxor -4325. +-2929337694275698696311924426 = bnot(2929337694275698696311924425). +0 = 2929337694275698696311924425 bsl -281. +11381466426987286010056685843059868836669048747613621092418532667143480310195248513703294481583824492589324697600 = 2929337694275698696311924425 bsr -281. +-51912714165724719765 = -51912714165724719694 + -71. +-51912714165724719623 = -51912714165724719694 - -71. +3685802705766455098274 = -51912714165724719694 * -71. +51912714165724719694 = -(-51912714165724719694). +-51912714165724719694 = +(-51912714165724719694). +731164988249643939 = -51912714165724719694 div -71. +-25 = -51912714165724719694 rem -71. +-51912714165724719696 = -51912714165724719694 band -71. +-69 = -51912714165724719694 bor -71. +51912714165724719627 = -51912714165724719694 bxor -71. +51912714165724719693 = bnot(-51912714165724719694). +-1 = -51912714165724719694 bsl -426. +-8996050581678828194654071155591618815918926338360260452875684958610849308208012689624562657875494921399574264624661808260863722667206971809507311616 = -51912714165724719694 bsr -426. +-914986716689646585310455939687 = 77389166885648 + -914986716689646662699622825335. +914986716689646740088789710983 = 77389166885648 - -914986716689646662699622825335. +-70810059716046191723759306493834876622292080 = 77389166885648 * -914986716689646662699622825335. +-77389166885648 = -(77389166885648). +77389166885648 = +(77389166885648). +0 = 77389166885648 div -914986716689646662699622825335. +77389166885648 = 77389166885648 rem -914986716689646662699622825335. +4400492315136 = 77389166885648 band -914986716689646662699622825335. +-914986716689646589710948254823 = 77389166885648 bor -914986716689646662699622825335. +-914986716689646594111440569959 = 77389166885648 bxor -914986716689646662699622825335. +-77389166885649 = bnot(77389166885648). +1 = 77389166885648 bsl -46. +5445778486698710331683766272 = 77389166885648 bsr -46. +-975537694281819 = -9957624 + -975537684324195. +975537674366571 = -9957624 - -975537684324195. +9714037458331027912680 = -9957624 * -975537684324195. +9957624 = -(-9957624). +-9957624 = +(-9957624). +0 = -9957624 div -975537684324195. +-9957624 = -9957624 rem -975537684324195. +-975537694048248 = -9957624 band -975537684324195. +-233571 = -9957624 bor -975537684324195. +975537693814677 = -9957624 bxor -975537684324195. +9957623 = bnot(-9957624). +-1368565421627670528 = -9957624 bsl 37. +-1 = -9957624 bsr 37. +94302615120 = 437658273 + 93864956847. +-93427298574 = 437658273 - 93864956847. +41080774908877545231 = 437658273 * 93864956847. +-437658273 = -(437658273). +437658273 = +(437658273). +0 = 437658273 div 93864956847. +437658273 = 437658273 rem 93864956847. +436208289 = 437658273 band 93864956847. +93866406831 = 437658273 bor 93864956847. +93430198542 = 437658273 bxor 93864956847. +-437658274 = bnot(437658273). +32293480615090828255451676672 = 437658273 bsl 66. +0 = 437658273 bsr 66. +-943791 = -944115 + 324. +-944439 = -944115 - 324. +-305893260 = -944115 * 324. +944115 = -(-944115). +-944115 = +(-944115). +-2913 = -944115 div 324. +-303 = -944115 rem 324. +4 = -944115 band 324. +-943795 = -944115 bor 324. +-943799 = -944115 bxor 324. +944114 = bnot(-944115). +-1 = -944115 bsl -76. +-71335312511591601454857584640 = -944115 bsr -76. +804168 = 47752 + 756416. +-708664 = 47752 - 756416. +36120376832 = 47752 * 756416. +-47752 = -(47752). +47752 = +(47752). +0 = 47752 div 756416. +47752 = 47752 rem 756416. +35456 = 47752 band 756416. +768712 = 47752 bor 756416. +733256 = 47752 bxor 756416. +-47753 = bnot(47752). +12613560225395143421908464704666750497243998756438437462327189888720866097444362744811186401573703018173245854859007204336994930330686119887393868649781145338264640467160245389612633716042357706582006584916450334337438323517736288076505564354961762912664223157514392448270336 = 47752 bsl 895. +0 = 47752 bsr 895. +-1884722603876 = -898353346699 + -986369257177. +88015910478 = -898353346699 - -986369257177. +886108123265964575008723 = -898353346699 * -986369257177. +898353346699 = -(-898353346699). +-898353346699 = +(-898353346699). +0 = -898353346699 div -986369257177. +-898353346699 = -898353346699 rem -986369257177. +-1055122816731 = -898353346699 band -986369257177. +-829599787145 = -898353346699 bor -986369257177. +225523029586 = -898353346699 bxor -986369257177. +898353346698 = bnot(-898353346699). +-28747307094368 = -898353346699 bsl 5. +-28073542085 = -898353346699 bsr 5. +423856867381559151547629330 = -73393635644 + 423856867381559224941264974. +-423856867381559298334900618 = -73393635644 - 423856867381559224941264974. +-31108396489809386079946238802215133256 = -73393635644 * 423856867381559224941264974. +73393635644 = -(-73393635644). +-73393635644 = +(-73393635644). +0 = -73393635644 div 423856867381559224941264974. +-73393635644 = -73393635644 rem 423856867381559224941264974. +423856867381559220578140228 = -73393635644 band 423856867381559224941264974. +-69030510898 = -73393635644 bor 423856867381559224941264974. +-423856867381559289608651126 = -73393635644 bxor 423856867381559224941264974. +73393635643 = bnot(-73393635644). +-1 = -73393635644 bsl -951. +-1396960987869257021182404737770934090305346867905888782305430990308128968611284969672680394890041633710648474075566307385781440743432461872101582743469592870663924353071069797292284110104690003385191941662431781220632085690520925286314556403968101141362195770022335942242917544896735955404520947712 = -73393635644 bsr -951. +83129814239514894144774200099 = 846361 + 83129814239514894144773353738. +-83129814239514894144772507377 = 846361 - 83129814239514894144773353738. +70357832709570065323264520443047418 = 846361 * 83129814239514894144773353738. +-846361 = -(846361). +846361 = +(846361). +0 = 846361 div 83129814239514894144773353738. +846361 = 846361 rem 83129814239514894144773353738. +57352 = 846361 band 83129814239514894144773353738. +83129814239514894144774142747 = 846361 bor 83129814239514894144773353738. +83129814239514894144774085395 = 846361 bxor 83129814239514894144773353738. +-846362 = bnot(846361). +99816706619824517513266074272494132712041761282277466793778573140068334740824421706264571914002764129848897354981634954162960368061493044290229001702400876756223308697960448 = 846361 bsl 555. +0 = 846361 bsr 555. +-6149219841637342341767709375 = 7936914143828558 + -6149219841645279255911537933. +6149219841653216170055366491 = 7936914143828558 - -6149219841645279255911537933. +-48805829934665622608982731067028238465690614 = 7936914143828558 * -6149219841645279255911537933. +-7936914143828558 = -(7936914143828558). +7936914143828558 = +(7936914143828558). +0 = 7936914143828558 div -6149219841645279255911537933. +7936914143828558 = 7936914143828558 rem -6149219841645279255911537933. +2270027655070274 = 7936914143828558 band -6149219841645279255911537933. +-6149219841639612369422779649 = 7936914143828558 bor -6149219841645279255911537933. +-6149219841641882397077849923 = 7936914143828558 bxor -6149219841645279255911537933. +-7936914143828559 = bnot(7936914143828558). +1015925010410055424 = 7936914143828558 bsl 7. +62007141748660 = 7936914143828558 bsr 7. +-9623489537571151649536261155 = -9623489537571151649536252669 + -8486. +-9623489537571151649536244183 = -9623489537571151649536252669 - -8486. +81664932215828792897964640149134 = -9623489537571151649536252669 * -8486. +9623489537571151649536252669 = -(-9623489537571151649536252669). +-9623489537571151649536252669 = +(-9623489537571151649536252669). +1134043075367800100110329 = -9623489537571151649536252669 div -8486. +-775 = -9623489537571151649536252669 rem -8486. +-9623489537571151649536261118 = -9623489537571151649536252669 band -8486. +-37 = -9623489537571151649536252669 bor -8486. +9623489537571151649536261081 = -9623489537571151649536252669 bxor -8486. +9623489537571151649536252668 = bnot(-9623489537571151649536252669). +-44142919870828739211200701535155062110435384245131017753869244786479539088619838914209774386582838431752616390853683553030701068582912 = -9623489537571151649536252669 bsl 351. +-1 = -9623489537571151649536252669 bsr 351. +2217835715205243105330672 = 2217834943852943918978847 + 771352299186351825. +2217834172500644732627022 = 2217834943852943918978847 - 771352299186351825. +1710732083156801799158171996743613274845775 = 2217834943852943918978847 * 771352299186351825. +-2217834943852943918978847 = -(2217834943852943918978847). +2217834943852943918978847 = +(2217834943852943918978847). +2875255 = 2217834943852943918978847 div 771352299186351825. +388855889902388472 = 2217834943852943918978847 rem 771352299186351825. +194851138756298257 = 2217834943852943918978847 band 771352299186351825. +2217835520354104349032415 = 2217834943852943918978847 bor 771352299186351825. +2217835325502965592734158 = 2217834943852943918978847 bxor 771352299186351825. +-2217834943852943918978848 = bnot(2217834943852943918978847). +0 = 2217834943852943918978847 bsl -777. +1762933184547032271860867896688770063313984512531651045139630090111197779460986334458776585482400710991208227030812046357442194506276242298380162967879430699127512261438594192361631181535584738325550599656143411847624343045336965677373191327400246575192080384 = 2217834943852943918978847 bsr -777. +92438122089066 = 4912779 + 92438117176287. +-92438112263508 = 4912779 - 92438117176287. +454128040863202071573 = 4912779 * 92438117176287. +-4912779 = -(4912779). +4912779 = +(4912779). +0 = 4912779 div 92438117176287. +4912779 = 4912779 rem 92438117176287. +152203 = 4912779 band 92438117176287. +92438121936863 = 4912779 bor 92438117176287. +92438121784660 = 4912779 bxor 92438117176287. +-4912780 = bnot(4912779). +314417856 = 4912779 bsl 6. +76762 = 4912779 bsr 6. +39620715882967338 = 39587992666517787 + 32723216449551. +39555269450068236 = 39587992666517787 - 32723216449551. +1295446452829699203068729663637 = 39587992666517787 * 32723216449551. +-39587992666517787 = -(39587992666517787). +39587992666517787 = +(39587992666517787). +1209 = 39587992666517787 div 32723216449551. +25623979010628 = 39587992666517787 rem 32723216449551. +5501047799819 = 39587992666517787 band 32723216449551. +39615214835167519 = 39587992666517787 bor 32723216449551. +39609713787367700 = 39587992666517787 bxor 32723216449551. +-39587992666517788 = bnot(39587992666517787). +633407882664284592 = 39587992666517787 bsl 4. +2474249541657361 = 39587992666517787 bsr 4. +768874092916150731214 = 768881411673972895468 + -7318757822164254. +768888730431795059722 = 768881411673972895468 - -7318757822164254. +-5627256846005583089915510094668200872 = 768881411673972895468 * -7318757822164254. +-768881411673972895468 = -(768881411673972895468). +768881411673972895468 = +(768881411673972895468). +-105056 = 768881411673972895468 div -7318757822164254. +1989908685027244 = 768881411673972895468 rem -7318757822164254. +768874093234249269984 = 768881411673972895468 band -7318757822164254. +-318098538770 = 768881411673972895468 bor -7318757822164254. +-768874093552347808754 = 768881411673972895468 bxor -7318757822164254. +-768881411673972895469 = bnot(768881411673972895468). +1744597869527381584003786176799407787844738102215515492761961756558697632737056644556336255557654110596433804500802027126351973090052059686348113033076149181819228376621109013589970153641994880427935169332083607354819336020908133882778522143888586620649102893574792953387671612174288395085127937425408 = 768881411673972895468 bsl 928. +0 = 768881411673972895468 bsr 928. +97523379246321139975 = 97523379246321146323 + -6348. +97523379246321152671 = 97523379246321146323 - -6348. +-619078411455646636858404 = 97523379246321146323 * -6348. +-97523379246321146323 = -(97523379246321146323). +97523379246321146323 = +(97523379246321146323). +-15362851173018454 = 97523379246321146323 div -6348. +331 = 97523379246321146323 rem -6348. +97523379246321139984 = 97523379246321146323 band -6348. +-9 = 97523379246321146323 bor -6348. +-97523379246321139993 = 97523379246321146323 bxor -6348. +-97523379246321146324 = bnot(97523379246321146323). +12190422405790143290 = 97523379246321146323 bsl -3. +780187033970569170584 = 97523379246321146323 bsr -3. +26473395236717784918939914261 = 26473395236717784918939914226 + 35. +26473395236717784918939914191 = 26473395236717784918939914226 - 35. +926568833285122472162896997910 = 26473395236717784918939914226 * 35. +-26473395236717784918939914226 = -(26473395236717784918939914226). +26473395236717784918939914226 = +(26473395236717784918939914226). +756382721049079569112568977 = 26473395236717784918939914226 div 35. +31 = 26473395236717784918939914226 rem 35. +34 = 26473395236717784918939914226 band 35. +26473395236717784918939914227 = 26473395236717784918939914226 bor 35. +26473395236717784918939914193 = 26473395236717784918939914226 bxor 35. +-26473395236717784918939914227 = bnot(26473395236717784918939914226). +27462941423975092133770269895553664313413731473513731049365080553912333227837462701951873909017702412472899040824845665565845174978755925962484247416291407045000410969434175858998730926298219165286384212639744 = 26473395236717784918939914226 bsl 598. +0 = 26473395236717784918939914226 bsr 598. +44253593145128125682376644835 = -5238646474973384 + 44253593145133364328851618219. +-44253593145138602975326591603 = -5238646474973384 - 44253593145133364328851618219. +-231828929734659208811078400956033413354483096 = -5238646474973384 * 44253593145133364328851618219. +5238646474973384 = -(-5238646474973384). +-5238646474973384 = +(-5238646474973384). +0 = -5238646474973384 div 44253593145133364328851618219. +-5238646474973384 = -5238646474973384 rem 44253593145133364328851618219. +44253593145132800824777382184 = -5238646474973384 band 44253593145133364328851618219. +-4675142400737349 = -5238646474973384 bor 44253593145133364328851618219. +-44253593145137475967178119533 = -5238646474973384 bxor 44253593145133364328851618219. +5238646474973383 = bnot(-5238646474973384). +-2879976356520494944057556992 = -5238646474973384 bsl 39. +-9530 = -5238646474973384 bsr 39. +-61074776157 = -61599175326 + 524399169. +-62123574495 = -61599175326 - 524399169. +-32302556352039704094 = -61599175326 * 524399169. +61599175326 = -(-61599175326). +-61599175326 = +(-61599175326). +-117 = -61599175326 div 524399169. +-244472553 = -61599175326 rem 524399169. +138485824 = -61599175326 band 524399169. +-61213261981 = -61599175326 bor 524399169. +-61351747805 = -61599175326 bxor 524399169. +61599175325 = bnot(-61599175326). +-230 = -61599175326 bsl -28. +-16535402717858758656 = -61599175326 bsr -28. +46569222308238723841 = 97243965961854867 + 46471978342276868974. +-46374734376315014107 = 97243965961854867 - 46471978342276868974. +4519119480096428414454840194163196458 = 97243965961854867 * 46471978342276868974. +-97243965961854867 = -(97243965961854867). +97243965961854867 = +(97243965961854867). +0 = 97243965961854867 div 46471978342276868974. +97243965961854867 = 97243965961854867 rem 46471978342276868974. +20585147107904258 = 97243965961854867 band 46471978342276868974. +46548637161130819583 = 97243965961854867 bor 46471978342276868974. +46528052014022915325 = 97243965961854867 bxor 46471978342276868974. +-97243965961854868 = bnot(97243965961854867). +6077747872615929 = 97243965961854867 bsl -4. +1555903455389677872 = 97243965961854867 bsr -4. +-9443337600386540895 = -62221842737 + -9443337538164698158. +9443337475942855421 = -62221842737 - -9443337538164698158. +587581863212092584392149578446 = -62221842737 * -9443337538164698158. +62221842737 = -(-62221842737). +-62221842737 = +(-62221842737). +0 = -62221842737 div -9443337538164698158. +-62221842737 = -62221842737 rem -9443337538164698158. +-9443337582130756926 = -62221842737 band -9443337538164698158. +-18255783969 = -62221842737 bor -9443337538164698158. +9443337563874972957 = -62221842737 bxor -9443337538164698158. +62221842736 = bnot(-62221842737). +-3982197935168 = -62221842737 bsl 6. +-972216293 = -62221842737 bsr 6. +-92946333875615637858065426480 = -41989427184345 + -92946333875615595868638242135. +92946333875615553879211057790 = -41989427184345 - -92946333875615595868638242135. +3902763318321980061088044077940023391376575 = -41989427184345 * -92946333875615595868638242135. +41989427184345 = -(-41989427184345). +-41989427184345 = +(-41989427184345). +0 = -41989427184345 div -92946333875615595868638242135. +-41989427184345 = -41989427184345 rem -92946333875615595868638242135. +-92946333875615596006624552927 = -41989427184345 band -92946333875615595868638242135. +-41851440873553 = -41989427184345 bor -92946333875615595868638242135. +92946333875615554155183679374 = -41989427184345 bxor -92946333875615595868638242135. +41989427184344 = bnot(-41989427184345). +-78212 = -41989427184345 bsl -29. +-22542902066816892272640 = -41989427184345 bsr -29. +73412760701 = 73412756377 + 4324. +73412752053 = 73412756377 - 4324. +317436758574148 = 73412756377 * 4324. +-73412756377 = -(73412756377). +73412756377 = +(73412756377). +16977973 = 73412756377 div 4324. +1125 = 73412756377 rem 4324. +128 = 73412756377 band 4324. +73412760573 = 73412756377 bor 4324. +73412760445 = 73412756377 bxor 4324. +-73412756378 = bnot(73412756377). +4588297273 = 73412756377 bsl -4. +1174604102032 = 73412756377 bsr -4. +8615882880057551270 = 4665767863572685 + 8611217112193978585. +-8606551344330405900 = 4665767863572685 - 8611217112193978585. +40177940068321845575900022480950725 = 4665767863572685 * 8611217112193978585. +-4665767863572685 = -(4665767863572685). +4665767863572685 = +(4665767863572685). +0 = 4665767863572685 div 8611217112193978585. +4665767863572685 = 4665767863572685 rem 8611217112193978585. +17955648983241 = 4665767863572685 band 8611217112193978585. +8615864924408568029 = 4665767863572685 bor 8611217112193978585. +8615846968759584788 = 4665767863572685 bxor 8611217112193978585. +-4665767863572686 = bnot(4665767863572685). +0 = 4665767863572685 bsl -93. +46207526818621075710052698991316946145771520 = 4665767863572685 bsr -93. +-39467433864158659742658 = -39467433864217874379444 + 59214636786. +-39467433864277089016230 = -39467433864217874379444 - 59214636786. +-2337049761145137873347751604626984 = -39467433864217874379444 * 59214636786. +39467433864217874379444 = -(-39467433864217874379444). +-39467433864217874379444 = +(-39467433864217874379444). +-666514834952 = -39467433864217874379444 div 59214636786. +-54456635172 = -39467433864217874379444 rem 59214636786. +40953447488 = -39467433864217874379444 band 59214636786. +-39467433864199613190146 = -39467433864217874379444 bor 59214636786. +-39467433864240566637634 = -39467433864217874379444 bxor 59214636786. +39467433864217874379443 = bnot(-39467433864217874379444). +-335402457668306942374505095499667157298433588811630592532361265952607363769192115735984351204439323261922619019955576664690066828623553597851655044917278817794907884804757365885534387240588638854958716813312 = -39467433864217874379444 bsl 611. +-1 = -39467433864217874379444 bsr 611. +6126905 = 6126912 + -7. +6126919 = 6126912 - -7. +-42888384 = 6126912 * -7. +-6126912 = -(6126912). +6126912 = +(6126912). +-875273 = 6126912 div -7. +1 = 6126912 rem -7. +6126912 = 6126912 band -7. +-7 = 6126912 bor -7. +-6126919 = 6126912 bxor -7. +-6126913 = bnot(6126912). +0 = 6126912 bsl -32. +26314886665469952 = 6126912 bsr -32. +-7154169647745 = -7154169647741 + -4. +-7154169647737 = -7154169647741 - -4. +28616678590964 = -7154169647741 * -4. +7154169647741 = -(-7154169647741). +-7154169647741 = +(-7154169647741). +1788542411935 = -7154169647741 div -4. +-1 = -7154169647741 rem -4. +-7154169647744 = -7154169647741 band -4. +-1 = -7154169647741 bor -4. +7154169647743 = -7154169647741 bxor -4. +7154169647740 = bnot(-7154169647741). +-1 = -7154169647741 bsl -244. +-202245178288604698038496862819314736706844432058191949633859085890283884187663525216256 = -7154169647741 bsr -244. +3690966049 = 4242728246 + -551762197. +4794490443 = 4242728246 - -551762197. +-2340977058286916462 = 4242728246 * -551762197. +-4242728246 = -(4242728246). +4242728246 = +(4242728246). +-7 = 4242728246 div -551762197. +380392867 = 4242728246 rem -551762197. +3691037730 = 4242728246 band -551762197. +-71681 = 4242728246 bor -551762197. +-3691109411 = 4242728246 bxor -551762197. +-4242728247 = bnot(4242728246). +1086138430976 = 4242728246 bsl 8. +16573157 = 4242728246 bsr 8. +-28899446413897218455215387171 = -328252375 + -28899446413897218454887134796. +28899446413897218454558882421 = -328252375 - -28899446413897218454887134796. +9486311921546994963710532353732140500 = -328252375 * -28899446413897218454887134796. +328252375 = -(-328252375). +-328252375 = +(-328252375). +0 = -328252375 div -28899446413897218454887134796. +-328252375 = -328252375 rem -28899446413897218454887134796. +-28899446413897218455156621280 = -328252375 band -28899446413897218454887134796. +-58765891 = -328252375 bor -28899446413897218454887134796. +28899446413897218455097855389 = -328252375 bxor -28899446413897218454887134796. +328252374 = bnot(-328252375). +-41031547 = -328252375 bsl -3. +-2626019000 = -328252375 bsr -3. +3625286175567416254712 = 85876386829 + 3625286175481539867883. +-3625286175395663481054 = 85876386829 - 3625286175481539867883. +311326477971478693042906061313007 = 85876386829 * 3625286175481539867883. +-85876386829 = -(85876386829). +85876386829 = +(85876386829). +0 = 85876386829 div 3625286175481539867883. +85876386829 = 85876386829 rem 3625286175481539867883. +12190753801 = 85876386829 band 3625286175481539867883. +3625286175555225500911 = 85876386829 bor 3625286175481539867883. +3625286175543034747110 = 85876386829 bxor 3625286175481539867883. +-85876386830 = bnot(85876386829). +0 = 85876386829 bsl -43. +755376686959001895698432 = 85876386829 bsr -43. +89427374879114797914 = 486913296 + 89427374878627884618. +-89427374878140971322 = 486913296 - 89427374878627884618. +43543377854780303256858080928 = 486913296 * 89427374878627884618. +-486913296 = -(486913296). +486913296 = +(486913296). +0 = 486913296 div 89427374878627884618. +486913296 = 486913296 rem 89427374878627884618. +67380224 = 486913296 band 89427374878627884618. +89427374879047417690 = 486913296 bor 89427374878627884618. +89427374878980037466 = 486913296 bxor 89427374878627884618. +-486913297 = bnot(486913296). +0 = 486913296 bsl -676. +152661210848739746084796801219929303017091608483351569718679717829647832381127607004270259131421098930744261831142132636907808415233236106921022961095308743313013280041597545067006268505764100610866637431694688256 = 486913296 bsr -676. +-6999135574145138500199069 = -6999135574144648672339887 + -489827859182. +-6999135574144158844480705 = -6999135574144648672339887 - -489827859182. +3428371594407851689973765427877792434 = -6999135574144648672339887 * -489827859182. +6999135574144648672339887 = -(-6999135574144648672339887). +-6999135574144648672339887 = +(-6999135574144648672339887). +14288969977806 = -6999135574144648672339887 div -489827859182. +-65639025195 = -6999135574144648672339887 rem -489827859182. +-6999135574144648806662128 = -6999135574144648672339887 band -489827859182. +-489693536941 = -6999135574144648672339887 bor -489827859182. +6999135574144159113125187 = -6999135574144648672339887 bxor -489827859182. +6999135574144648672339886 = bnot(-6999135574144648672339887). +-1970081522727088896154641004058086735872 = -6999135574144648672339887 bsl 48. +-24865924695 = -6999135574144648672339887 bsr 48. +28133112160341859011 = 8294987549896678 + 28124817172791962333. +-28116522185242065655 = 8294987549896678 - 28124817172791962333. +233295008291429613932376743017829774 = 8294987549896678 * 28124817172791962333. +-8294987549896678 = -(8294987549896678). +8294987549896678 = +(8294987549896678). +0 = 8294987549896678 div 28124817172791962333. +8294987549896678 = 8294987549896678 rem 28124817172791962333. +3773748453976772 = 8294987549896678 band 28124817172791962333. +28129338411887882239 = 8294987549896678 bor 28124817172791962333. +28125564663433905467 = 8294987549896678 bxor 28124817172791962333. +-8294987549896679 = bnot(8294987549896678). +1263082162412447579800888840669276340899121737001091513533517862335233925901939815520623946825386759209517435329525794796703333180486616796703609541310798284672613427814355760158969931165101163017718864257813588701421019625991708955623833787170994552942292643771145249627718231570271772775626465609777152 = 8294987549896678 bsl 954. +0 = 8294987549896678 bsr 954. +-779237291937111325192769 = -779237253649537953318198 + -38287573371874571. +-779237215361964581443627 = -779237253649537953318198 - -38287573371874571. +29835103523204720212081208891876907743058 = -779237253649537953318198 * -38287573371874571. +779237253649537953318198 = -(-779237253649537953318198). +-779237253649537953318198 = +(-779237253649537953318198). +20352223 = -779237253649537953318198 div -38287573371874571. +-22256284756296865 = -779237253649537953318198 rem -38287573371874571. +-779237291934568402545984 = -779237253649537953318198 band -38287573371874571. +-2542922646785 = -779237253649537953318198 bor -38287573371874571. +779237291932025479899199 = -779237253649537953318198 bxor -38287573371874571. +779237253649537953318197 = bnot(-779237253649537953318198). +-6087791044137015260299 = -779237253649537953318198 bsl -7. +-99742368467140858024729344 = -779237253649537953318198 bsr -7. +-298617752514520 = 3 + -298617752514523. +298617752514526 = 3 - -298617752514523. +-895853257543569 = 3 * -298617752514523. +-3 = -(3). +3 = +(3). +0 = 3 div -298617752514523. +3 = 3 rem -298617752514523. +1 = 3 band -298617752514523. +-298617752514521 = 3 bor -298617752514523. +-298617752514522 = 3 bxor -298617752514523. +-4 = bnot(3). +0 = 3 bsl -9. +1536 = 3 bsr -9. +-133 = -47 + -86. +39 = -47 - -86. +4042 = -47 * -86. +47 = -(-47). +-47 = +(-47). +0 = -47 div -86. +-47 = -47 rem -86. +-128 = -47 band -86. +-5 = -47 bor -86. +123 = -47 bxor -86. +46 = bnot(-47). +-1 = -47 bsl -74. +-887804898779493300174848 = -47 bsr -74. +-509981125680411160658784391928 = -826657747793126416252762779123 + 316676622112715255593978387195. +-1143334369905841671846741166318 = -826657747793126416252762779123 - 316676622112715255593978387195. +-261783183214432167649135582111582362841923892371405556529985 = -826657747793126416252762779123 * 316676622112715255593978387195. +826657747793126416252762779123 = -(-826657747793126416252762779123). +-826657747793126416252762779123 = +(-826657747793126416252762779123). +-2 = -826657747793126416252762779123 div 316676622112715255593978387195. +-193304503567695905064806004733 = -826657747793126416252762779123 rem 316676622112715255593978387195. +123847801736915507221384729097 = -826657747793126416252762779123 band 316676622112715255593978387195. +-633828927417326667880169121025 = -826657747793126416252762779123 bor 316676622112715255593978387195. +-757676729154242175101553850122 = -826657747793126416252762779123 bxor 316676622112715255593978387195. +826657747793126416252762779122 = bnot(-826657747793126416252762779123). +-1 = -826657747793126416252762779123 bsl -736. +-298815106411787030647290347359184362814657491801384110694109341430405716236858687575876812387232946571630146667000682675592981845434535225432344189083261459357626833404822948698396070901561854958883208841441498296598547928675344224375690492086507798528 = -826657747793126416252762779123 bsr -736. +-64584896933529 = -64584813557954 + -83375575. +-64584730182379 = -64584813557954 - -83375575. +5384795966662210573550 = -64584813557954 * -83375575. +64584813557954 = -(-64584813557954). +-64584813557954 = +(-64584813557954). +774625 = -64584813557954 div -83375575. +-8773579 = -64584813557954 rem -83375575. +-64584882765272 = -64584813557954 band -83375575. +-14168257 = -64584813557954 bor -83375575. +64584868597015 = -64584813557954 bxor -83375575. +64584813557953 = bnot(-64584813557954). +-4133428067709056 = -64584813557954 bsl 6. +-1009137711844 = -64584813557954 bsr 6. +5445452782307633783919491483 = 5445459651994218436231385824 + -6869686584652311894341. +5445466521680803088543280165 = 5445459651994218436231385824 - -6869686584652311894341. +-37408601118570129338094041961378427211853093221984 = 5445459651994218436231385824 * -6869686584652311894341. +-5445459651994218436231385824 = -(5445459651994218436231385824). +5445459651994218436231385824 = +(5445459651994218436231385824). +-792679 = 5445459651994218436231385824 div -6869686584652311894341. +3359758608496137056285 = 5445459651994218436231385824 rem -6869686584652311894341. +5445457804436360510423843488 = 5445459651994218436231385824 band -6869686584652311894341. +-5022128726726504352005 = 5445459651994218436231385824 bor -6869686584652311894341. +-5445462826565087236928195493 = 5445459651994218436231385824 bxor -6869686584652311894341. +-5445459651994218436231385825 = bnot(5445459651994218436231385824). +424541713960740958963994971066282255333546899910452547992056400302574875373415528379911049066750750745702499309271450700245418359668606110820892628974614398415116198945474660651745336645526790587577936231743543715623590567622817663647964067135091598708138221633309269545040067703054877683963344265271410827531273633792 = 5445459651994218436231385824 bsl 963. +0 = 5445459651994218436231385824 bsr 963. +-56292853672347789967622755530 = -2348 + -56292853672347789967622753182. +56292853672347789967622750834 = -2348 - -56292853672347789967622753182. +132175620422672610843978224471336 = -2348 * -56292853672347789967622753182. +2348 = -(-2348). +-2348 = +(-2348). +0 = -2348 div -56292853672347789967622753182. +-2348 = -2348 rem -56292853672347789967622753182. +-56292853672347789967622753216 = -2348 band -56292853672347789967622753182. +-2314 = -2348 bor -56292853672347789967622753182. +56292853672347789967622750902 = -2348 bxor -56292853672347789967622753182. +2347 = bnot(-2348). +-161353331376128 = -2348 bsl 36. +-1 = -2348 bsr 36. +81677755761110325989 = 81677755761141741122 + -31415133. +81677755761173156255 = 81677755761141741122 - -31415133. +-2565917560377784029199199226 = 81677755761141741122 * -31415133. +-81677755761141741122 = -(81677755761141741122). +81677755761141741122 = +(81677755761141741122). +-2599949386212 = 81677755761141741122 div -31415133. +23394926 = 81677755761141741122 rem -31415133. +81677755761110852610 = 81677755761141741122 band -31415133. +-526621 = 81677755761141741122 bor -31415133. +-81677755761111379231 = 81677755761141741122 bxor -31415133. +-81677755761141741123 = bnot(81677755761141741122). +0 = 81677755761141741122 bsl -441. +463801217193409525842586227224346187120848525564428471008166082428333282429928854270435247339902105628804687447690604120298658543401340136044500661305344 = 81677755761141741122 bsr -441. +3686559983349955873379 = 3686559983349881939528 + 73933851. +3686559983349808005677 = 3686559983349881939528 - 73933851. +272561576511552652184654162328 = 3686559983349881939528 * 73933851. +-3686559983349881939528 = -(3686559983349881939528). +3686559983349881939528 = +(3686559983349881939528). +49862950914728 = 3686559983349881939528 div 73933851. +68282000 = 3686559983349881939528 rem 73933851. +2106376 = 3686559983349881939528 band 73933851. +3686559983349953767003 = 3686559983349881939528 bor 73933851. +3686559983349951660627 = 3686559983349881939528 bxor 73933851. +-3686559983349881939529 = bnot(3686559983349881939528). +2423975815203786007743325477570123552079224796171620812901156999316537218240556378219798115949609720528071885440199041531037808941745592396171939222230680705206120186559996389841922298304117353704995561336328522084056218553932578816 = 3686559983349881939528 bsl 697. +0 = 3686559983349881939528 bsr 697. +57484957125928146 = -7693579689369341 + 65178536815297487. +-72872116504666828 = -7693579689369341 - 65178536815297487. +-501456267024984596441840332146067 = -7693579689369341 * 65178536815297487. +7693579689369341 = -(-7693579689369341). +-7693579689369341 = +(-7693579689369341). +0 = -7693579689369341 div 65178536815297487. +-7693579689369341 = -7693579689369341 rem 65178536815297487. +64328614120784131 = -7693579689369341 band 65178536815297487. +-6843656994855985 = -7693579689369341 bor 65178536815297487. +-71172271115640116 = -7693579689369341 bxor 65178536815297487. +7693579689369340 = bnot(-7693579689369341). +-1102825898098619242482183019680173987957272873402146047893375711191417365700739748008122193597413717796130157914356711424 = -7693579689369341 bsl 346. +-1 = -7693579689369341 bsr 346. +-519158957389930531939580311985 = -519158957389938888268468295316 + 8356328887983331. +-519158957389947244597356278647 = -519158957389938888268468295316 - 8356328887983331. +-4338262993092853551931673024332658790593377596 = -519158957389938888268468295316 * 8356328887983331. +519158957389938888268468295316 = -(-519158957389938888268468295316). +-519158957389938888268468295316 = +(-519158957389938888268468295316). +-62127635753603 = -519158957389938888268468295316 div 8356328887983331. +-94845381103723 = -519158957389938888268468295316 rem 8356328887983331. +8356293808359520 = -519158957389938888268468295316 band 8356328887983331. +-519158957389938888233388671505 = -519158957389938888268468295316 bor 8356328887983331. +-519158957389947244527197031025 = -519158957389938888268468295316 bxor 8356328887983331. +519158957389938888268468295315 = bnot(-519158957389938888268468295316). +-4055929354608897564597408558 = -519158957389938888268468295316 bsl -7. +-66452346545912177698363941800448 = -519158957389938888268468295316 bsr -7. +-28977693743494607236553 = 327952916 + -28977693743494935189469. +28977693743495263142385 = 327952916 - -28977693743494935189469. +-9503319162134120026617371041604 = 327952916 * -28977693743494935189469. +-327952916 = -(327952916). +327952916 = +(327952916). +0 = 327952916 div -28977693743494935189469. +327952916 = 327952916 rem -28977693743494935189469. +285222912 = 327952916 band -28977693743494935189469. +-28977693743494892459465 = 327952916 bor -28977693743494935189469. +-28977693743495177682377 = 327952916 bxor -28977693743494935189469. +-327952917 = bnot(327952916). +0 = 327952916 bsl -829. +1174026506388461224997001534527826734857654163263098943331637410142530672452265566015726828228263252542300150382587480100197773428316022689359675598503380136107671318105408084540110960461813695296459050154533107209859133108602988474181342077223930952671035392 = 327952916 bsr -829. +-2695050304640900494 = -3466487676266667 + -2691583816964633827. +2688117329288367160 = -3466487676266667 - -2691583816964633827. +9330342131146699470866724060744609 = -3466487676266667 * -2691583816964633827. +3466487676266667 = -(-3466487676266667). +-3466487676266667 = +(-3466487676266667). +0 = -3466487676266667 div -2691583816964633827. +-3466487676266667 = -3466487676266667 rem -2691583816964633827. +-2692728133733317867 = -3466487676266667 band -2691583816964633827. +-2322170907582627 = -3466487676266667 bor -2691583816964633827. +2690405962825735240 = -3466487676266667 bxor -2691583816964633827. +3466487676266666 = bnot(-3466487676266667). +-1 = -3466487676266667 bsl -996. +-2321482113640535431413620257407215827129049952400819330081663821876398892083620880412644946852926812279497835369537647617146819081816303894972183011212579895044715021815984947621783999582159904772883937113585197454877221630252530865836836630100784077944139096919685291647777681531880061996596278375284733806077018112 = -3466487676266667 bsr -996. +-22437719121122816933 = -23285647816458958477 + 847928695336141544. +-24133576511795100021 = -23285647816458958477 - 847928695336141544. +-19744568973066917792526540430090668488 = -23285647816458958477 * 847928695336141544. +23285647816458958477 = -(-23285647816458958477). +-23285647816458958477 = +(-23285647816458958477). +-27 = -23285647816458958477 div 847928695336141544. +-391573042383136789 = -23285647816458958477 rem 847928695336141544. +630577232458088544 = -23285647816458958477 band 847928695336141544. +-23068296353580905477 = -23285647816458958477 bor 847928695336141544. +-23698873586038994021 = -23285647816458958477 bxor 847928695336141544. +23285647816458958476 = bnot(-23285647816458958477). +-38817258929776399754088580725456443760777990968496296036332720682810882753979348016638665186177153265633575379988311077403580431663080426551349837729969580718177343869422008191109185431721874421090512735255464683562656344729123003655067404229022059383475929088 = -23285647816458958477 bsl 798. +-1 = -23285647816458958477 bsr 798. +-989442199970150700183057 = -989442199876381553248442 + -93769146934615. +-989442199782612406313827 = -989442199876381553248442 - -93769146934615. +92779151023517125455724277559824619830 = -989442199876381553248442 * -93769146934615. +989442199876381553248442 = -(-989442199876381553248442). +-989442199876381553248442 = +(-989442199876381553248442). +10551895076 = -989442199876381553248442 div -93769146934615. +-56297040792702 = -989442199876381553248442 rem -93769146934615. +-989442199899747529125376 = -989442199876381553248442 band -93769146934615. +-70403171057681 = -989442199876381553248442 bor -93769146934615. +989442199829344358067695 = -989442199876381553248442 bxor -93769146934615. +989442199876381553248441 = bnot(-989442199876381553248442). +-3957768799505526212993768 = -989442199876381553248442 bsl 2. +-247360549969095388312111 = -989442199876381553248442 bsr 2. +-454565619835185753747499735 = 23857 + -454565619835185753747523592. +454565619835185753747547449 = 23857 - -454565619835185753747523592. +-10844571992408026527154670334344 = 23857 * -454565619835185753747523592. +-23857 = -(23857). +23857 = +(23857). +0 = 23857 div -454565619835185753747523592. +23857 = 23857 rem -454565619835185753747523592. +21808 = 23857 band -454565619835185753747523592. +-454565619835185753747521543 = 23857 bor -454565619835185753747523592. +-454565619835185753747543351 = 23857 bxor -454565619835185753747523592. +-23858 = bnot(23857). +381712 = 23857 bsl 4. +1491 = 23857 bsr 4. +4424861271793435821209060 = -895284491 + 4424861271793436716493551. +-4424861271793437611778042 = -895284491 - 4424861271793436716493551. +-3961509671463199647866640111817541 = -895284491 * 4424861271793436716493551. +895284491 = -(-895284491). +-895284491 = +(-895284491). +0 = -895284491 div 4424861271793436716493551. +-895284491 = -895284491 rem 4424861271793436716493551. +4424861271793436714863333 = -895284491 band 4424861271793436716493551. +-893654273 = -895284491 bor 4424861271793436716493551. +-4424861271793437608517606 = -895284491 bxor 4424861271793436716493551. +895284490 = bnot(-895284491). +-20335232416252554641923252366849810142015369362484154992319414677966476941037681564548311931469593765231637616504453672554373676561313854128128 = -895284491 bsl 443. +-1 = -895284491 bsr 443. +-479897902363968905109082 = -479897986781358672282469 + 84417389767173387. +-479898071198748439455856 = -479897986781358672282469 - 84417389767173387. +-40511735398603776920128864530205763452503 = -479897986781358672282469 * 84417389767173387. +479897986781358672282469 = -(-479897986781358672282469). +-479897986781358672282469 = +(-479897986781358672282469). +-5684823 = -479897986781358672282469 div 84417389767173387. +-67832966756876968 = -479897986781358672282469 rem 84417389767173387. +72594190081467403 = -479897986781358672282469 band 84417389767173387. +-479897974958158986576485 = -479897986781358672282469 bor 84417389767173387. +-479898047552349068043888 = -479897986781358672282469 bxor 84417389767173387. +479897986781358672282468 = bnot(-479897986781358672282469). +-1 = -479897986781358672282469 bsl -554. +-28298702654068005841545709516918834456567407751897587427005307095333461302591905673285423371447222444481771769836293532214420357015734577061387734681527826892801158705423150865290221632618496 = -479897986781358672282469 bsr -554. +-63589298 = -63688694 + 99396. +-63788090 = -63688694 - 99396. +-6330401428824 = -63688694 * 99396. +63688694 = -(-63688694). +-63688694 = +(-63688694). +-640 = -63688694 div 99396. +-75254 = -63688694 rem 99396. +0 = -63688694 band 99396. +-63589298 = -63688694 bor 99396. +-63589298 = -63688694 bxor 99396. +63688693 = bnot(-63688694). +-1 = -63688694 bsl -366. +-9572839033616149482117465315062621977561566009507969171174157968312164591652007173476852839438977804043377850519126016 = -63688694 bsr -366. +38915975846452919995301805206 = 463577688 + 38915975846452919994838227518. +-38915975846452919994374649830 = 463577688 - 38915975846452919994838227518. +18040578109162487652056077446812418384 = 463577688 * 38915975846452919994838227518. +-463577688 = -(463577688). +463577688 = +(463577688). +0 = 463577688 div 38915975846452919994838227518. +463577688 = 463577688 rem 38915975846452919994838227518. +444662296 = 463577688 band 38915975846452919994838227518. +38915975846452919994857142910 = 463577688 bor 38915975846452919994838227518. +38915975846452919994412480614 = 463577688 bxor 38915975846452919994838227518. +-463577689 = bnot(463577688). +0 = 463577688 bsl -934. +67319126996976393712644982790218279208550252032390219414949744296596194471837978968081786211424320887982063355469556203181254294641466766425359065272182089051181133983012727913586133826172285933782992420679866256197858058290960678672764073003328205861839447865053537609972137876760236654592 = 463577688 bsr -934. +-138361293209433 = 674896677931891 + -813257971141324. +1488154649073215 = 674896677931891 - -813257971141324. +-548865103024909248965207563684 = 674896677931891 * -813257971141324. +-674896677931891 = -(674896677931891). +674896677931891 = +(674896677931891). +0 = 674896677931891 div -813257971141324. +674896677931891 = 674896677931891 rem -813257971141324. +4743800062256 = 674896677931891 band -813257971141324. +-143105093271689 = 674896677931891 bor -813257971141324. +-147848893333945 = 674896677931891 bxor -813257971141324. +-674896677931892 = bnot(674896677931891). +94983263351489061205990965248 = 674896677931891 bsl 47. +4 = 674896677931891 bsr 47. +627853533456289133315151352 = 627853534329433388814597617 + -873144255499446265. +627853535202577644314043882 = 627853534329433388814597617 - -873144255499446265. +-548206706794769143536531955029983892288550505 = 627853534329433388814597617 * -873144255499446265. +-627853534329433388814597617 = -(627853534329433388814597617). +627853534329433388814597617 = +(627853534329433388814597617). +-719071940 = 627853534329433388814597617 div -873144255499446265. +627590894115293517 = 627853534329433388814597617 rem -873144255499446265. +627853533749023109104031745 = 627853534329433388814597617 band -873144255499446265. +-292733975788880393 = 627853534329433388814597617 bor -873144255499446265. +-627853534041757084892912138 = 627853534329433388814597617 bxor -873144255499446265. +-627853534329433388814597618 = bnot(627853534329433388814597617). +80365252394167473768268494976 = 627853534329433388814597617 bsl 7. +4905105736948698350114043 = 627853534329433388814597617 bsr 7. +-21576635897 = 626 + -21576636523. +21576637149 = 626 - -21576636523. +-13506974463398 = 626 * -21576636523. +-626 = -(626). +626 = +(626). +0 = 626 div -21576636523. +626 = 626 rem -21576636523. +528 = 626 band -21576636523. +-21576636425 = 626 bor -21576636523. +-21576636953 = 626 bxor -21576636523. +-627 = bnot(626). +1126528014153616374255758842324569857460972158422799924928429195382004130200140562727887787800414270630340196022633632138851349820295772642127732201288637029325733888 = 626 bsl 539. +0 = 626 bsr 539. +-327875629828116419647977544 = -327875629828116419647977461 + -83. +-327875629828116419647977378 = -327875629828116419647977461 - -83. +27213677275733662830782129263 = -327875629828116419647977461 * -83. +327875629828116419647977461 = -(-327875629828116419647977461). +-327875629828116419647977461 = +(-327875629828116419647977461). +3950308793109836381300933 = -327875629828116419647977461 div -83. +-22 = -327875629828116419647977461 rem -83. +-327875629828116419647977463 = -327875629828116419647977461 band -83. +-81 = -327875629828116419647977461 bor -83. +327875629828116419647977382 = -327875629828116419647977461 bxor -83. +327875629828116419647977460 = bnot(-327875629828116419647977461). +-10246113432128638113999296 = -327875629828116419647977461 bsl -5. +-10492020154499725428735278752 = -327875629828116419647977461 bsr -5. +9315714251516243906868654 = 9315714251516325428488326 + -81521619672. +9315714251516406950107998 = 9315714251516325428488326 - -81521619672. +-759432114185144030880207746063949072 = 9315714251516325428488326 * -81521619672. +-9315714251516325428488326 = -(9315714251516325428488326). +9315714251516325428488326 = +(9315714251516325428488326). +-114272928935880 = 9315714251516325428488326 div -81521619672. +32393856966 = 9315714251516325428488326 rem -81521619672. +9315714251516323801090048 = 9315714251516325428488326 band -81521619672. +-79894221394 = 9315714251516325428488326 bor -81521619672. +-9315714251516403695311442 = 9315714251516325428488326 bxor -81521619672. +-9315714251516325428488327 = bnot(9315714251516325428488326). +1273487671781282264641552716631249308204448980984801118850118055677058047356019203824800731291141143228184946951674778353664 = 9315714251516325428488326 bsl 326. +0 = 9315714251516325428488326 bsr 326. +59719273612193636529940 = -46 + 59719273612193636529986. +-59719273612193636530032 = -46 - 59719273612193636529986. +-2747086586160907280379356 = -46 * 59719273612193636529986. +46 = -(-46). +-46 = +(-46). +0 = -46 div 59719273612193636529986. +-46 = -46 rem 59719273612193636529986. +59719273612193636529986 = -46 band 59719273612193636529986. +-46 = -46 bor 59719273612193636529986. +-59719273612193636530032 = -46 bxor 59719273612193636529986. +45 = bnot(-46). +-1 = -46 bsl -682. +-923027997860813832599966181230491327725660823554481496951755224384924618139899131077685015368534350419773927945648948725886893781694240485015409391212411953346024661529191785876527911616053943612974127120384 = -46 bsr -682. +8239777107128 = -9584735 + 8239786691863. +-8239796276598 = -9584735 - 8239786691863. +-78976171898033511305 = -9584735 * 8239786691863. +9584735 = -(-9584735). +-9584735 = +(-9584735). +0 = -9584735 div 8239786691863. +-9584735 = -9584735 rem 8239786691863. +8239778172161 = -9584735 band 8239786691863. +-1065033 = -9584735 bor 8239786691863. +-8239779237194 = -9584735 bxor 8239786691863. +9584734 = bnot(-9584735). +-1 = -9584735 bsl -546. +-2207789901237298349168515420337438685802160456150401071122584087718795318977399464587385366042827588336888176608306170711999671293512097614322126374505966913691887641559040 = -9584735 bsr -546. +864214577958738583386 = -999868 + 864214577958739583254. +-864214577958740583122 = -999868 - 864214577958739583254. +-864100501634449029629010472 = -999868 * 864214577958739583254. +999868 = -(-999868). +-999868 = +(-999868). +0 = -999868 div 864214577958739583254. +-999868 = -999868 rem 864214577958739583254. +864214577958738731012 = -999868 band 864214577958739583254. +-147626 = -999868 bor 864214577958739583254. +-864214577958738878638 = -999868 bxor 864214577958739583254. +999867 = bnot(-999868). +-1 = -999868 bsl -44. +-17589863875858137088 = -999868 bsr -44. +742429259336656208630042 = 742429266981345577992641 + -7644689369362599. +742429274626034947355240 = 742429266981345577992641 - -7644689369362599. +-5675641124795959371173671938168082633959 = 742429266981345577992641 * -7644689369362599. +-742429266981345577992641 = -(742429266981345577992641). +742429266981345577992641 = +(742429266981345577992641). +-97116996 = 742429266981345577992641 div -7644689369362599. +75715528360037 = 742429266981345577992641 rem -7644689369362599. +742429262468394699456833 = 742429266981345577992641 band -7644689369362599. +-3131738490826791 = 742429266981345577992641 bor -7644689369362599. +-742429265600133190283624 = 742429266981345577992641 bxor -7644689369362599. +-742429266981345577992642 = bnot(742429266981345577992641). +56096369380706971764952345809247950674566578176 = 742429266981345577992641 bsl 76. +9 = 742429266981345577992641 bsr 76. +-63822114144981621 = -34 + -63822114144981587. +63822114144981553 = -34 - -63822114144981587. +2169951880929373958 = -34 * -63822114144981587. +34 = -(-34). +-34 = +(-34). +0 = -34 div -63822114144981587. +-34 = -34 rem -63822114144981587. +-63822114144981620 = -34 band -63822114144981587. +-1 = -34 bor -63822114144981587. +63822114144981619 = -34 bxor -63822114144981587. +33 = bnot(-34). +-18253611008 = -34 bsl 29. +-1 = -34 bsr 29. +-2686231576924555149905426542 = -2686231576924555149813974296 + -91452246. +-2686231576924555149722522050 = -2686231576924555149813974296 - -91452246. +245661910985872341001354431555468816 = -2686231576924555149813974296 * -91452246. +2686231576924555149813974296 = -(-2686231576924555149813974296). +-2686231576924555149813974296 = +(-2686231576924555149813974296). +29373051996170276122 = -2686231576924555149813974296 div -91452246. +-16904284 = -2686231576924555149813974296 rem -91452246. +-2686231576924555149884258136 = -2686231576924555149813974296 band -91452246. +-21168406 = -2686231576924555149813974296 bor -91452246. +2686231576924555149863089730 = -2686231576924555149813974296 bxor -91452246. +2686231576924555149813974295 = bnot(-2686231576924555149813974296). +-145620906 = -2686231576924555149813974296 bsl -64. +-49552226422244501234349603813943975169109262336 = -2686231576924555149813974296 bsr -64. +-7794906949236057903 = -8239525163563949492 + 444618214327891589. +-8684143377891841081 = -8239525163563949492 - 444618214327891589. +-3663442965133532096405715590047622788 = -8239525163563949492 * 444618214327891589. +8239525163563949492 = -(-8239525163563949492). +-8239525163563949492 = +(-8239525163563949492). +-18 = -8239525163563949492 div 444618214327891589. +-236397305661900890 = -8239525163563949492 rem 444618214327891589. +298101241817375236 = -8239525163563949492 band 444618214327891589. +-8093008191053433139 = -8239525163563949492 bor 444618214327891589. +-8391109432870808375 = -8239525163563949492 bxor 444618214327891589. +8239525163563949491 = bnot(-8239525163563949492). +-1 = -8239525163563949492 bsl -269. +-7815756456038475044314658489534671849000407135891980184024346413048071743431833478349947290521698304 = -8239525163563949492 bsr -269. +-9469201222362472158468 = -9511385564486716393926 + 42184342124244235458. +-9553569906610960629384 = -9511385564486716393926 - 42184342124244235458. +-401231542727905526424290941252210625028108 = -9511385564486716393926 * 42184342124244235458. +9511385564486716393926 = -(-9511385564486716393926). +-9511385564486716393926 = +(-9511385564486716393926). +-225 = -9511385564486716393926 div 42184342124244235458. +-19908586531763415876 = -9511385564486716393926 rem 42184342124244235458. +4683851916089193474 = -9511385564486716393926 band 42184342124244235458. +-9473885074278561351942 = -9511385564486716393926 bor 42184342124244235458. +-9478568926194650545416 = -9511385564486716393926 bxor 42184342124244235458. +9511385564486716393925 = bnot(-9511385564486716393926). +-1 = -9511385564486716393926 bsl -872. +-299502192571225438047488105658859863385967144993669725823404832331225269910529398842051240815323832342514425020449726133790958582625570706749851376388969819379334603895213893319813641128404044517800989825299954131142773830774705719482501075599631003152051945016770640324681096543338496 = -9511385564486716393926 bsr -872. +-82327367158839231346468686 = -82327367158839231414763514 + 68294828. +-82327367158839231483058342 = -82327367158839231414763514 - 68294828. +-5622533379805773989123470849305592 = -82327367158839231414763514 * 68294828. +82327367158839231414763514 = -(-82327367158839231414763514). +-82327367158839231414763514 = +(-82327367158839231414763514). +-1205470012441340820 = -82327367158839231414763514 div 68294828. +-23484554 = -82327367158839231414763514 rem 68294828. +4 = -82327367158839231414763514 band 68294828. +-82327367158839231346468690 = -82327367158839231414763514 bor 68294828. +-82327367158839231346468694 = -82327367158839231414763514 bxor 68294828. +82327367158839231414763513 = bnot(-82327367158839231414763514). +-1 = -82327367158839231414763514 bsl -862. +-2531631490728627937601786650854934811248022860364659715090149968584266679474566383501961515903027741185156659521588388177636000048472950697199597078612943528485007433241218981825673198379847255299771693621571458318840535791756308399134792078730413455274294383363650980665154094975942656 = -82327367158839231414763514 bsr -862. +576646511682247658 = 2852342282936486 + 573794169399311172. +-570941827116374686 = 2852342282936486 - 573794169399311172. +1636657371080076004094657826221592 = 2852342282936486 * 573794169399311172. +-2852342282936486 = -(2852342282936486). +2852342282936486 = +(2852342282936486). +0 = 2852342282936486 div 573794169399311172. +2852342282936486 = 2852342282936486 rem 573794169399311172. +565151124971524 = 2852342282936486 band 573794169399311172. +576081360557276134 = 2852342282936486 bor 573794169399311172. +575516209432304610 = 2852342282936486 bxor 573794169399311172. +-2852342282936487 = bnot(2852342282936486). +802862977660366763796847394816 = 2852342282936486 bsl 48. +10 = 2852342282936486 bsr 48. +-3924188576621262044924576719 = -2961569231199212855 + -3924188573659692813725363864. +3924188570698123582526151009 = -2961569231199212855 - -3924188573659692813725363864. +11621756137174072111357977307746881505261271720 = -2961569231199212855 * -3924188573659692813725363864. +2961569231199212855 = -(-2961569231199212855). +-2961569231199212855 = +(-2961569231199212855). +0 = -2961569231199212855 div -3924188573659692813725363864. +-2961569231199212855 = -2961569231199212855 rem -3924188573659692813725363864. +-3924188576542156021877931960 = -2961569231199212855 band -3924188573659692813725363864. +-79106023046644759 = -2961569231199212855 bor -3924188573659692813725363864. +3924188576463049998831287201 = -2961569231199212855 bxor -3924188573659692813725363864. +2961569231199212854 = bnot(-2961569231199212855). +-5784314904685963 = -2961569231199212855 bsl -9. +-1516323446373996981760 = -2961569231199212855 bsr -9. +-7831461881754721320824764644 = -7831461881754721314434837393 + -6389927251. +-7831461881754721308044910142 = -7831461881754721314434837393 - -6389927251. +50042471693392233425017707121284496643 = -7831461881754721314434837393 * -6389927251. +7831461881754721314434837393 = -(-7831461881754721314434837393). +-7831461881754721314434837393 = +(-7831461881754721314434837393). +1225594842340204494 = -7831461881754721314434837393 div -6389927251. +-5311571399 = -7831461881754721314434837393 rem -6389927251. +-7831461881754721319406006227 = -7831461881754721314434837393 band -6389927251. +-1418758417 = -7831461881754721314434837393 bor -6389927251. +7831461881754721317987247810 = -7831461881754721314434837393 bxor -6389927251. +7831461881754721314434837392 = bnot(-7831461881754721314434837393). +-442783854038468215329094768091161141255478419537582706029054537536642857581179154220410293681154686976 = -7831461881754721314434837393 bsl 245. +-1 = -7831461881754721314434837393 bsr 245. +194621195850105967080077323 = 96387968691682123552961471 + 98233227158423843527115852. +-1845258466741719974154381 = 96387968691682123552961471 - 98233227158423843527115852. +9468501223829055524727701090123235136541605909338292 = 96387968691682123552961471 * 98233227158423843527115852. +-96387968691682123552961471 = -(96387968691682123552961471). +96387968691682123552961471 = +(96387968691682123552961471). +0 = 96387968691682123552961471 div 98233227158423843527115852. +96387968691682123552961471 = 96387968691682123552961471 rem 98233227158423843527115852. +78583429525471920982360076 = 96387968691682123552961471 band 98233227158423843527115852. +116037766324634046097717247 = 96387968691682123552961471 bor 98233227158423843527115852. +37454336799162125115357171 = 96387968691682123552961471 bxor 98233227158423843527115852. +-96387968691682123552961472 = bnot(96387968691682123552961471). +5610518197743345 = 96387968691682123552961471 bsl -34. +1655932693034586511551203367572209664 = 96387968691682123552961471 bsr -34. +-6176529541955489 = -6176529541946177 + -9312. +-6176529541936865 = -6176529541946177 - -9312. +57515843094602800224 = -6176529541946177 * -9312. +6176529541946177 = -(-6176529541946177). +-6176529541946177 = +(-6176529541946177). +663287107167 = -6176529541946177 div -9312. +-7073 = -6176529541946177 rem -9312. +-6176529541955424 = -6176529541946177 band -9312. +-65 = -6176529541946177 bor -9312. +6176529541955359 = -6176529541946177 bxor -9312. +6176529541946176 = bnot(-6176529541946177). +-1 = -6176529541946177 bsl -282. +-47995807212208277884944016617820070836245614453104659072077011457368858099803947103643668713578692608 = -6176529541946177 bsr -282. +-579636899835487569585335692 = -579636899835487569585335765 + 73. +-579636899835487569585335838 = -579636899835487569585335765 - 73. +-42313493687990592579729510845 = -579636899835487569585335765 * 73. +579636899835487569585335765 = -(-579636899835487569585335765). +-579636899835487569585335765 = +(-579636899835487569585335765). +-7940231504595720131305969 = -579636899835487569585335765 div 73. +-28 = -579636899835487569585335765 rem 73. +9 = -579636899835487569585335765 band 73. +-579636899835487569585335701 = -579636899835487569585335765 bor 73. +-579636899835487569585335710 = -579636899835487569585335765 bxor 73. +579636899835487569585335764 = bnot(-579636899835487569585335765). +-1 = -579636899835487569585335765 bsl -938. +-1346765423176583012049052892147042667014251665156490772334510940228576398548649372195525300955339723355712093608524844502210775957221752905511057470718258827159087451739739288214013652339412227414100683885806358080844304086823596559794764688306073651238227667486207613978771789074030450792545845265846931292160 = -579636899835487569585335765 bsr -938. +-37156449122464181194286 = 382447 + -37156449122464181576733. +37156449122464181959180 = 382447 - -37156449122464181576733. +-14210372497539058851476805651 = 382447 * -37156449122464181576733. +-382447 = -(382447). +382447 = +(382447). +0 = 382447 div -37156449122464181576733. +382447 = 382447 rem -37156449122464181576733. +332259 = 382447 band -37156449122464181576733. +-37156449122464181526545 = 382447 bor -37156449122464181576733. +-37156449122464181858804 = 382447 bxor -37156449122464181576733. +-382448 = bnot(382447). +3267607335707377193126915465837706790293842145846939127631744887147137869862514545738527125050530725888 = 382447 bsl 322. +0 = 382447 bsr 322. +-3879793355513634615720575 = -481911 + -3879793355513634615238664. +3879793355513634614756753 = -481911 - -3879793355513634615238664. +1869715095748931171064279806904 = -481911 * -3879793355513634615238664. +481911 = -(-481911). +-481911 = +(-481911). +0 = -481911 div -3879793355513634615238664. +-481911 = -481911 rem -3879793355513634615238664. +-3879793355513634615720568 = -481911 band -3879793355513634615238664. +-7 = -481911 bor -3879793355513634615238664. +3879793355513634615720561 = -481911 bxor -3879793355513634615238664. +481910 = bnot(-481911). +-1 = -481911 bsl -92. +-2386307689088227574627647415648256 = -481911 bsr -92. +-685793482466922729770089 = 43851784289 + -685793482466966581554378. +685793482467010433338667 = 43851784289 - -685793482466966581554378. +-30073267859943522102494310379567242 = 43851784289 * -685793482466966581554378. +-43851784289 = -(43851784289). +43851784289 = +(43851784289). +0 = 43851784289 div -685793482466966581554378. +43851784289 = 43851784289 rem -685793482466966581554378. +9127133216 = 43851784289 band -685793482466966581554378. +-685793482466931856903305 = 43851784289 bor -685793482466966581554378. +-685793482466940984036521 = 43851784289 bxor -685793482466966581554378. +-43851784290 = bnot(43851784289). +0 = 43851784289 bsl -741. +507240656676445006921350498546236949549885605308873515813999060954631952492340984108575825868855107686850300348339344660908756789690404717943725680905979044051237707408360970203848608972443834876606623368978764950416702005167708438528 = 43851784289 bsr -741. +-64297936826539773755448431895 = 2395351967 + -64297936826539773757843783862. +64297936826539773760239135829 = 2395351967 - -64297936826539773757843783862. +-154016189451493784874586089352564556554 = 2395351967 * -64297936826539773757843783862. +-2395351967 = -(2395351967). +2395351967 = +(2395351967). +0 = 2395351967 div -64297936826539773757843783862. +2395351967 = 2395351967 rem -64297936826539773757843783862. +2361666314 = 2395351967 band -64297936826539773757843783862. +-64297936826539773757810098209 = 2395351967 bor -64297936826539773757843783862. +-64297936826539773760171764523 = 2395351967 bxor -64297936826539773757843783862. +-2395351968 = bnot(2395351967). +379558669840677493225295095876575821824 = 2395351967 bsl 97. +0 = 2395351967 bsr 97. +770813703325541 = 836295641311454 + -65481937985913. +901777579297367 = 836295641311454 - -65481937985913. +-54762259322245972818697547502 = 836295641311454 * -65481937985913. +-836295641311454 = -(836295641311454). +836295641311454 = +(836295641311454). +-12 = 836295641311454 div -65481937985913. +50512385480498 = 836295641311454 rem -65481937985913. +774130274175110 = 836295641311454 band -65481937985913. +-3316570849569 = 836295641311454 bor -65481937985913. +-777446845024679 = 836295641311454 bxor -65481937985913. +-836295641311455 = bnot(836295641311454). +0 = 836295641311454 bsl -782. +21272397638013034718728490721075051503817452457058679878289406207574916622366800339593607966879094691976196311442781198819613867431211340106115654351939124120269224915055093698208503418889470534301291559958922191784577789792542951420477967228643311616 = 836295641311454 bsr -782. +315 = -77 + 392. +-469 = -77 - 392. +-30184 = -77 * 392. +77 = -(-77). +-77 = +(-77). +0 = -77 div 392. +-77 = -77 rem 392. +384 = -77 band 392. +-69 = -77 bor 392. +-453 = -77 bxor 392. +76 = bnot(-77). +-41339060224 = -77 bsl 29. +-1 = -77 bsr 29. +-726958148793677870 = -726958148793677877 + 7. +-726958148793677884 = -726958148793677877 - 7. +-5088707041555745139 = -726958148793677877 * 7. +726958148793677877 = -(-726958148793677877). +-726958148793677877 = +(-726958148793677877). +-103851164113382553 = -726958148793677877 div 7. +-6 = -726958148793677877 rem 7. +3 = -726958148793677877 band 7. +-726958148793677873 = -726958148793677877 bor 7. +-726958148793677876 = -726958148793677877 bxor 7. +726958148793677876 = bnot(-726958148793677877). +-2839680268725305 = -726958148793677877 bsl -8. +-186101286091181536512 = -726958148793677877 bsr -8. +-27391664628842574182975932 = -31724496561664731869374853 + 4332831932822157686398921. +-36057328494486889555773774 = -31724496561664731869374853 - 4332831932822157686398921. +-137456911755087696017154216110617535911133043733613 = -31724496561664731869374853 * 4332831932822157686398921. +31724496561664731869374853 = -(-31724496561664731869374853). +-31724496561664731869374853 = +(-31724496561664731869374853). +-7 = -31724496561664731869374853 div 4332831932822157686398921. +-1394673031909628064582406 = -31724496561664731869374853 rem 4332831932822157686398921. +1813444657374202021451337 = -31724496561664731869374853 band 4332831932822157686398921. +-29205109286216776204427269 = -31724496561664731869374853 bor 4332831932822157686398921. +-31018553943590978225878606 = -31724496561664731869374853 bxor 4332831932822157686398921. +31724496561664731869374852 = bnot(-31724496561664731869374853). +-2454564032491009351568915678640966559254341004296192 = -31724496561664731869374853 bsl 86. +-1 = -31724496561664731869374853 bsr 86. +2275149 = -6 + 2275155. +-2275161 = -6 - 2275155. +-13650930 = -6 * 2275155. +6 = -(-6). +-6 = +(-6). +0 = -6 div 2275155. +-6 = -6 rem 2275155. +2275154 = -6 band 2275155. +-5 = -6 bor 2275155. +-2275159 = -6 bxor 2275155. +5 = bnot(-6). +-1325135298583788247187473125557188886870612922656714218591204650969464832 = -6 bsl 237. +-1 = -6 bsr 237. +-297695611366842322174181901 = -6 + -297695611366842322174181895. +297695611366842322174181889 = -6 - -297695611366842322174181895. +1786173668201053933045091370 = -6 * -297695611366842322174181895. +6 = -(-6). +-6 = +(-6). +0 = -6 div -297695611366842322174181895. +-6 = -6 rem -297695611366842322174181895. +-297695611366842322174181896 = -6 band -297695611366842322174181895. +-5 = -6 bor -297695611366842322174181895. +297695611366842322174181891 = -6 bxor -297695611366842322174181895. +5 = bnot(-6). +-1 = -6 bsl -398. +-3873374817130362884483878758004517811494558689243835269245989034810971433025261791944468029920206747153854757959121240064 = -6 bsr -398. +4526392995126238 = 4526392995561573 + -435335. +4526392995996908 = 4526392995561573 - -435335. +-1970497294722797381955 = 4526392995561573 * -435335. +-4526392995561573 = -(4526392995561573). +4526392995561573 = +(4526392995561573). +-10397493873 = 4526392995561573 div -435335. +359118 = 4526392995561573 rem -435335. +4526392995299425 = 4526392995561573 band -435335. +-173187 = 4526392995561573 bor -435335. +-4526392995472612 = 4526392995561573 bxor -435335. +-4526392995561574 = bnot(4526392995561573). +9492534123427943940096 = 4526392995561573 bsl 21. +2158352372 = 4526392995561573 bsr 21. +7887314996470303626382 = 7887373824819569326219 + -58828349265699837. +7887432653168835026056 = 7887373824819569326219 - -58828349265699837. +-464001182155624425965132306817588126303 = 7887373824819569326219 * -58828349265699837. +-7887373824819569326219 = -(7887373824819569326219). +7887373824819569326219 = +(7887373824819569326219). +-134074 = 7887373824819569326219 div -58828349265699837. +21725370129380281 = 7887373824819569326219 rem -58828349265699837. +7887355810341930080259 = 7887373824819569326219 band -58828349265699837. +-40813871626453877 = 7887373824819569326219 bor -58828349265699837. +-7887396624213556534136 = 7887373824819569326219 bxor -58828349265699837. +-7887373824819569326220 = bnot(7887373824819569326219). +985921728102446165777 = 7887373824819569326219 bsl -3. +63098990598556554609752 = 7887373824819569326219 bsr -3. +-39829885621163298980777562 = -4847991611 + -39829885621163294132785951. +39829885621163289284794340 = -4847991611 - -39829885621163294132785951. +193094951358489174016871810506657061 = -4847991611 * -39829885621163294132785951. +4847991611 = -(-4847991611). +-4847991611 = +(-4847991611). +0 = -4847991611 div -39829885621163294132785951. +-4847991611 = -4847991611 rem -39829885621163294132785951. +-39829885621163298442443583 = -4847991611 band -39829885621163294132785951. +-538333979 = -4847991611 bor -39829885621163294132785951. +39829885621163297904109604 = -4847991611 bxor -39829885621163294132785951. +4847991610 = bnot(-4847991611). +-1 = -4847991611 bsl -815. +-1059274032173169249210912480478494242895499365554911866173767690067157635577659137412971079812073458566849467649816801488739198889427389825097658891419842676658538651753087239335473072810778095703758240053305602292270128237182995593610156636408404139573248 = -4847991611 bsr -815. +-95223736697 = -95222763361 + -973336. +-95221790025 = -95222763361 - -973336. +92683743598742296 = -95222763361 * -973336. +95222763361 = -(-95222763361). +-95222763361 = +(-95222763361). +97831 = -95222763361 div -973336. +-329145 = -95222763361 rem -973336. +-95223209848 = -95222763361 band -973336. +-526849 = -95222763361 bor -973336. +95222682999 = -95222763361 bxor -973336. +95222763360 = bnot(-95222763361). +-1 = -95222763361 bsl -54. +-1715380806359154077124788224 = -95222763361 bsr -54. +82182257492664591951363162 = 82182257492664591951363615 + -453. +82182257492664591951364068 = 82182257492664591951363615 - -453. +-37228562644177060153967717595 = 82182257492664591951363615 * -453. +-82182257492664591951363615 = -(82182257492664591951363615). +82182257492664591951363615 = +(82182257492664591951363615). +-181417786959524485543849 = 82182257492664591951363615 div -453. +18 = 82182257492664591951363615 rem -453. +82182257492664591951363611 = 82182257492664591951363615 band -453. +-449 = 82182257492664591951363615 bor -453. +-82182257492664591951364060 = 82182257492664591951363615 bxor -453. +-82182257492664591951363616 = bnot(82182257492664591951363615). +0 = 82182257492664591951363615 bsl -89. +50868353534515221204638696196059782526438483039354880 = 82182257492664591951363615 bsr -89. +34336558417852744164668007 = 34336558417383317722736162 + 469426441931845. +34336558416913891280804317 = 34336558417383317722736162 - 469426441931845. +16118488446057193649802819013002520878890 = 34336558417383317722736162 * 469426441931845. +-34336558417383317722736162 = -(34336558417383317722736162). +34336558417383317722736162 = +(34336558417383317722736162). +73145769710 = 34336558417383317722736162 div 469426441931845. +51895837321212 = 34336558417383317722736162 rem 469426441931845. +11823306867712 = 34336558417383317722736162 band 469426441931845. +34336558417840920857800295 = 34336558417383317722736162 bor 469426441931845. +34336558417829097550932583 = 34336558417383317722736162 bxor 469426441931845. +-34336558417383317722736163 = bnot(34336558417383317722736162). +9438361309430711520968256731299708928 = 34336558417383317722736162 bsl 38. +124915671830907 = 34336558417383317722736162 bsr 38. +6363678596284926877774 = 6363678596284926877719 + 55. +6363678596284926877664 = 6363678596284926877719 - 55. +350002322795670978274545 = 6363678596284926877719 * 55. +-6363678596284926877719 = -(6363678596284926877719). +6363678596284926877719 = +(6363678596284926877719). +115703247205180488685 = 6363678596284926877719 div 55. +44 = 6363678596284926877719 rem 55. +23 = 6363678596284926877719 band 55. +6363678596284926877751 = 6363678596284926877719 bor 55. +6363678596284926877728 = 6363678596284926877719 bxor 55. +-6363678596284926877720 = bnot(6363678596284926877719). +0 = 6363678596284926877719 bsl -357. +1868171270807695465811717792912671932573589457822593548078554753678289760300921328694949457367392182152900585249481507182338899968 = 6363678596284926877719 bsr -357. +2836235199466365630442 = -876 + 2836235199466365631318. +-2836235199466365632194 = -876 - 2836235199466365631318. +-2484542034732536293034568 = -876 * 2836235199466365631318. +876 = -(-876). +-876 = +(-876). +0 = -876 div 2836235199466365631318. +-876 = -876 rem 2836235199466365631318. +2836235199466365630484 = -876 band 2836235199466365631318. +-42 = -876 bor 2836235199466365631318. +-2836235199466365630526 = -876 bxor 2836235199466365631318. +875 = bnot(-876). +-1926344371863552 = -876 bsl 41. +-1 = -876 bsr 41. +-47372461657264100128016242 = -786194966312368178575 + -47371675462297787759837667. +47370889267331475391659092 = -786194966312368178575 - -47371675462297787759837667. +37243372794241647509924771819376743578467384525 = -786194966312368178575 * -47371675462297787759837667. +786194966312368178575 = -(-786194966312368178575). +-786194966312368178575 = +(-786194966312368178575). +0 = -786194966312368178575 div -47371675462297787759837667. +-786194966312368178575 = -786194966312368178575 rem -47371675462297787759837667. +-47372414666538015693719023 = -786194966312368178575 band -47371675462297787759837667. +-46990726084434297219 = -786194966312368178575 bor -47371675462297787759837667. +47372367675811931259421804 = -786194966312368178575 bxor -47371675462297787759837667. +786194966312368178574 = bnot(-786194966312368178575). +-1 = -786194966312368178575 bsl -842. +-23056140391842376856942385979048877753494478796369537038283990637967359275756168535019576389602874038491715400459610608590330696454643966505877991077027671488589191268781221316986692007983001771463057149877393715414378574703287577707240626738075837126331648151212247534796800 = -786194966312368178575 bsr -842. +37024255800679 = 7448912425833 + 29575343374846. +-22126430949013 = 7448912425833 - 29575343374846. +220304142763168062892796718 = 7448912425833 * 29575343374846. +-7448912425833 = -(7448912425833). +7448912425833 = +(7448912425833). +0 = 7448912425833 div 29575343374846. +7448912425833 = 7448912425833 rem 29575343374846. +3049456533864 = 7448912425833 band 29575343374846. +33974799266815 = 7448912425833 bor 29575343374846. +30925342732951 = 7448912425833 bxor 29575343374846. +-7448912425834 = bnot(7448912425833). +232778513307 = 7448912425833 bsl -5. +238365197626656 = 7448912425833 bsr -5. +-8498864996039499763036 = -9265742822333137134835 + 766877826293637371799. +-10032620648626774506634 = -9265742822333137134835 - 766877826293637371799. +-7105692714586708823837484658209598489518165 = -9265742822333137134835 * 766877826293637371799. +9265742822333137134835 = -(-9265742822333137134835). +-9265742822333137134835 = +(-9265742822333137134835). +-12 = -9265742822333137134835 div 766877826293637371799. +-63208906809488673247 = -9265742822333137134835 rem 766877826293637371799. +176581658718206710533 = -9265742822333137134835 band 766877826293637371799. +-8675446654757706473569 = -9265742822333137134835 bor 766877826293637371799. +-8852028313475913184102 = -9265742822333137134835 bxor 766877826293637371799. +9265742822333137134834 = bnot(-9265742822333137134835). +-144777231598955267732 = -9265742822333137134835 bsl -6. +-593007540629320776629440 = -9265742822333137134835 bsr -6. +-56882487688527177609281 = -56882487688532411578145 + 5233968864. +-56882487688537645547009 = -56882487688532411578145 - 5233968864. +-297721169468641972054844032877280 = -56882487688532411578145 * 5233968864. +56882487688532411578145 = -(-56882487688532411578145). +-56882487688532411578145 = +(-56882487688532411578145). +-10867945371203 = -56882487688532411578145 div 5233968864. +-2987354753 = -56882487688532411578145 rem 5233968864. +4949803200 = -56882487688532411578145 band 5233968864. +-56882487688532127412481 = -56882487688532411578145 bor 5233968864. +-56882487688537077215681 = -56882487688532411578145 bxor 5233968864. +56882487688532411578144 = bnot(-56882487688532411578145). +-512351900715962790238789615423942819840 = -56882487688532411578145 bsl 53. +-6315225 = -56882487688532411578145 bsr 53. +64575 = -33319 + 97894. +-131213 = -33319 - 97894. +-3261730186 = -33319 * 97894. +33319 = -(-33319). +-33319 = +(-33319). +0 = -33319 div 97894. +-33319 = -33319 rem 97894. +97344 = -33319 band 97894. +-32769 = -33319 bor 97894. +-130113 = -33319 bxor 97894. +33318 = bnot(-33319). +-1 = -33319 bsl -363. +-626008722523530794560396832035391363321042934776610478176769823043853380062349109822135895417456867330568331722752 = -33319 bsr -363. +67769193761565562434810930047 = 67769193738113729497422973453 + 23451832937387956594. +67769193714661896560035016859 = 67769193738113729497422973453 - 23451832937387956594. +1589311809847721219260337275925999570019178299082 = 67769193738113729497422973453 * 23451832937387956594. +-67769193738113729497422973453 = -(67769193738113729497422973453). +67769193738113729497422973453 = +(67769193738113729497422973453). +2889718424 = 67769193738113729497422973453 div 23451832937387956594. +22373712892028885597 = 67769193738113729497422973453 rem 23451832937387956594. +23361758981359929344 = 67769193738113729497422973453 band 23451832937387956594. +67769193738203803453451000703 = 67769193738113729497422973453 bor 23451832937387956594. +67769193714842044472091071359 = 67769193738113729497422973453 bxor 23451832937387956594. +-67769193738113729497422973454 = bnot(67769193738113729497422973453). +2117787304316054046794467920 = 67769193738113729497422973453 bsl -5. +2168614199619639343917535150496 = 67769193738113729497422973453 bsr -5. +-7885694187608415931205573899 = -8273167911729764246432215673 + 387473724121348315226641774. +-8660641635851112561658857447 = -8273167911729764246432215673 - 387473724121348315226641774. +-3205635181039170021882665399154579563048311525879323902 = -8273167911729764246432215673 * 387473724121348315226641774. +8273167911729764246432215673 = -(-8273167911729764246432215673). +-8273167911729764246432215673 = +(-8273167911729764246432215673). +-21 = -8273167911729764246432215673 div 387473724121348315226641774. +-136219705181449626672738419 = -8273167911729764246432215673 rem 387473724121348315226641774. +387463095885847653291132166 = -8273167911729764246432215673 band 387473724121348315226641774. +-8273157283494263584496706065 = -8273167911729764246432215673 bor 387473724121348315226641774. +-8660620379380111237787838231 = -8273167911729764246432215673 bxor 387473724121348315226641774. +8273167911729764246432215672 = bnot(-8273167911729764246432215673). +-2068291977932441061608053919 = -8273167911729764246432215673 bsl -2. +-33092671646919056985728862692 = -8273167911729764246432215673 bsr -2. +-9340882561511109548174122 = -8616146697814932781717359 + -724735863696176766456763. +-7891410834118756015260596 = -8616146697814932781717359 - -724735863696176766456763. +6244430518773866671246836981563234056856560048917 = -8616146697814932781717359 * -724735863696176766456763. +8616146697814932781717359 = -(-8616146697814932781717359). +-8616146697814932781717359 = +(-8616146697814932781717359). +11 = -8616146697814932781717359 div -724735863696176766456763. +-644052197156988350692966 = -8616146697814932781717359 rem -724735863696176766456763. +-9340734807308439922137087 = -8616146697814932781717359 band -724735863696176766456763. +-147754202669626037035 = -8616146697814932781717359 bor -724735863696176766456763. +9340587053105770296100052 = -8616146697814932781717359 bxor -724735863696176766456763. +8616146697814932781717358 = bnot(-8616146697814932781717359). +-1 = -8616146697814932781717359 bsl -455. +-801606281495502293128590378590436882741939672196195224471519060616467399151958617949152781733879053032977845343629338540173896768533078295212512138385883777728512 = -8616146697814932781717359 bsr -455. +-721711695065839494 = -721711699848178775 + 4782339281. +-721711704630518056 = -721711699848178775 - 4782339281. +-3451470211741227091992960775 = -721711699848178775 * 4782339281. +721711699848178775 = -(-721711699848178775). +-721711699848178775 = +(-721711699848178775). +-150911856 = -721711699848178775 div 4782339281. +-2930763239 = -721711699848178775 rem 4782339281. +67899521 = -721711699848178775 band 4782339281. +-721711695133739015 = -721711699848178775 bor 4782339281. +-721711695201638536 = -721711699848178775 bxor 4782339281. +721711699848178774 = bnot(-721711699848178775). +-109061988533053345959846156529321168076800 = -721711699848178775 bsl 77. +-1 = -721711699848178775 bsr 77. +733733191817308369 = 733733191817313955 + -5586. +733733191817319541 = 733733191817313955 - -5586. +-4098633609491515752630 = 733733191817313955 * -5586. +-733733191817313955 = -(733733191817313955). +733733191817313955 = +(733733191817313955). +-131352164664753 = 733733191817313955 div -5586. +3697 = 733733191817313955 rem -5586. +733733191817308706 = 733733191817313955 band -5586. +-337 = 733733191817313955 bor -5586. +-733733191817309043 = 733733191817313955 bxor -5586. +-733733191817313956 = bnot(733733191817313955). +5538162991525838594741869954611567113668786757581083286911736941383154599216724252392860416284411687606958361153300446379109181948976694609697270551828111996701734676461057576930545500160 = 733733191817313955 bsl 561. +0 = 733733191817313955 bsr 561. +94448894682821423222216 = 94448894682821423222291 + -75. +94448894682821423222366 = 94448894682821423222291 - -75. +-7083667101211606741671825 = 94448894682821423222291 * -75. +-94448894682821423222291 = -(94448894682821423222291). +94448894682821423222291 = +(94448894682821423222291). +-1259318595770952309630 = 94448894682821423222291 div -75. +41 = 94448894682821423222291 rem -75. +94448894682821423222289 = 94448894682821423222291 band -75. +-73 = 94448894682821423222291 bor -75. +-94448894682821423222362 = 94448894682821423222291 bxor -75. +-94448894682821423222292 = bnot(94448894682821423222291). +2951527958838169475696 = 94448894682821423222291 bsl -5. +3022364629850285543113312 = 94448894682821423222291 bsr -5. +8281516573311517468 = 29388669 + 8281516573282128799. +-8281516573252740130 = 29388669 - 8281516573282128799. +243382749390202726889178531 = 29388669 * 8281516573282128799. +-29388669 = -(29388669). +29388669 = +(29388669). +0 = 29388669 div 8281516573282128799. +29388669 = 29388669 rem 8281516573282128799. +29377309 = 29388669 band 8281516573282128799. +8281516573282140159 = 29388669 bor 8281516573282128799. +8281516573252762850 = 29388669 bxor 8281516573282128799. +-29388670 = bnot(29388669). +0 = 29388669 bsl -516. +6304602068298530802555856986719955291286766182900851726331355532331216818815000284114895397254950905461564494075161261146530244310801391837457379857631751736131584 = 29388669 bsr -516. +73857 = 73381 + 476. +72905 = 73381 - 476. +34929356 = 73381 * 476. +-73381 = -(73381). +73381 = +(73381). +154 = 73381 div 476. +77 = 73381 rem 476. +132 = 73381 band 476. +73725 = 73381 bor 476. +73593 = 73381 bxor 476. +-73382 = bnot(73381). +18785536 = 73381 bsl 8. +286 = 73381 bsr 8. +-672 = -678 + 6. +-684 = -678 - 6. +-4068 = -678 * 6. +678 = -(-678). +-678 = +(-678). +-113 = -678 div 6. +0 = -678 rem 6. +2 = -678 band 6. +-674 = -678 bor 6. +-676 = -678 bxor 6. +677 = bnot(-678). +-11 = -678 bsl -6. +-43392 = -678 bsr -6. +646871226767987500146156850189 = 646871226767894615366929898452 + 92884779226951737. +646871226767801730587702946715 = 646871226767894615366929898452 - 92884779226951737. +60084491086603324173941866316678094918915011124 = 646871226767894615366929898452 * 92884779226951737. +-646871226767894615366929898452 = -(646871226767894615366929898452). +646871226767894615366929898452 = +(646871226767894615366929898452). +6964232807049 = 646871226767894615366929898452 div 92884779226951737. +53875763773504339 = 646871226767894615366929898452 rem 92884779226951737. +90619621955096592 = 646871226767894615366929898452 band 92884779226951737. +646871226767896880524201753597 = 646871226767894615366929898452 bor 92884779226951737. +646871226767806260902246657005 = 646871226767894615366929898452 bxor 92884779226951737. +-646871226767894615366929898453 = bnot(646871226767894615366929898452). +0 = 646871226767894615366929898452 bsl -275. +39270519047433881707202790258921294936734613845970943458816343766813625805071514463646288271302578826787722100736 = 646871226767894615366929898452 bsr -275. +-7 = -3 + -4. +1 = -3 - -4. +12 = -3 * -4. +3 = -(-3). +-3 = +(-3). +0 = -3 div -4. +-3 = -3 rem -4. +-4 = -3 band -4. +-3 = -3 bor -4. +1 = -3 bxor -4. +2 = bnot(-3). +-1 = -3 bsl -7. +-384 = -3 bsr -7. +714249984402415 = 5123119881 + 714244861282534. +-714239738162653 = 5123119881 - 714244861282534. +3659162048738637093458454 = 5123119881 * 714244861282534. +-5123119881 = -(5123119881). +5123119881 = +(5123119881). +0 = 5123119881 div 714244861282534. +5123119881 = 5123119881 rem 714244861282534. +287049728 = 5123119881 band 714244861282534. +714249697352687 = 5123119881 bor 714244861282534. +714249410302959 = 5123119881 bxor 714244861282534. +-5123119882 = bnot(5123119881). +655759344768 = 5123119881 bsl 7. +40024374 = 5123119881 bsr 7. +959939234339641868150277905 = 959893656998498311384448464 + 45577341143556765829441. +959848079657354754618619023 = 959893656998498311384448464 - 45577341143556765829441. +43749400666556822964792371935459754694087278428624 = 959893656998498311384448464 * 45577341143556765829441. +-959893656998498311384448464 = -(959893656998498311384448464). +959893656998498311384448464 = +(959893656998498311384448464). +21060 = 959893656998498311384448464 div 45577341143556765829441. +34852515192823016421004 = 959893656998498311384448464 rem 45577341143556765829441. +5354212576714157230400 = 959893656998498311384448464 band 45577341143556765829441. +959933880127065153993047505 = 959893656998498311384448464 bor 45577341143556765829441. +959928525914488439835817105 = 959893656998498311384448464 bxor 45577341143556765829441. +-959893656998498311384448465 = bnot(959893656998498311384448464). +104071878 = 959893656998498311384448464 bsl -63. +8853456314314218895471508657041030238449958912 = 959893656998498311384448464 bsr -63. +59247603122112336157 = 462133893243347993 + 58785469228868988164. +-58323335335625640171 = 462133893243347993 - 58785469228868988164. +27166757760874259441608768381650154852 = 462133893243347993 * 58785469228868988164. +-462133893243347993 = -(462133893243347993). +462133893243347993 = +(462133893243347993). +0 = 462133893243347993 div 58785469228868988164. +462133893243347993 = 462133893243347993 rem 58785469228868988164. +453122219436942336 = 462133893243347993 band 58785469228868988164. +58794480902675393821 = 462133893243347993 bor 58785469228868988164. +58341358683238451485 = 462133893243347993 bxor 58785469228868988164. +-462133893243347994 = bnot(462133893243347993). +902605260240914 = 462133893243347993 bsl -9. +236612553340594172416 = 462133893243347993 bsr -9. +-698011569432077309818 = -35126663965523543 + -697976442768111786275. +697941316104146262732 = -35126663965523543 - -697976442768111786275. +24517583960966937814813969629296772325 = -35126663965523543 * -697976442768111786275. +35126663965523543 = -(-35126663965523543). +-35126663965523543 = +(-35126663965523543). +0 = -35126663965523543 div -697976442768111786275. +-35126663965523543 = -35126663965523543 rem -697976442768111786275. +-697985602812498640759 = -35126663965523543 band -697976442768111786275. +-25966619578669059 = -35126663965523543 bor -697976442768111786275. +697959636192919971700 = -35126663965523543 bxor -697976442768111786275. +35126663965523542 = bnot(-35126663965523543). +-1 = -35126663965523543 bsl -439. +-49866053955979679484958059718662141146464390837730256639612968936119505528878470902001368771063691814798804304753403053643510683012393077590861021184 = -35126663965523543 bsr -439. +-347226718057629 = -269767376619753 + -77459341437876. +-192308035181877 = -269767376619753 - -77459341437876. +20896003334389534767523964628 = -269767376619753 * -77459341437876. +269767376619753 = -(-269767376619753). +-269767376619753 = +(-269767376619753). +3 = -269767376619753 div -77459341437876. +-37389352306125 = -269767376619753 rem -77459341437876. +-272107596934140 = -269767376619753 band -77459341437876. +-75119121123489 = -269767376619753 bor -77459341437876. +196988475810651 = -269767376619753 bxor -77459341437876. +269767376619752 = bnot(-269767376619753). +-2671646694484568040711421504928585273573376 = -269767376619753 bsl 93. +-1 = -269767376619753 bsr 93. +58815216586799 = 4212156 + 58815212374643. +-58815208162487 = 4212156 - 58815212374643. +247738849695126760308 = 4212156 * 58815212374643. +-4212156 = -(4212156). +4212156 = +(4212156). +0 = 4212156 div 58815212374643. +4212156 = 4212156 rem 58815212374643. +4210736 = 4212156 band 58815212374643. +58815212376063 = 4212156 bor 58815212374643. +58815208165327 = 4212156 bxor 58815212374643. +-4212157 = bnot(4212156). +1053039 = 4212156 bsl -2. +16848624 = 4212156 bsr -2. +-88676814525367380585 = -88239588111222488472 + -437226414144892113. +-87802361697077596359 = -88239588111222488472 - -437226414144892113. +38580678695492062162453604775826221336 = -88239588111222488472 * -437226414144892113. +88239588111222488472 = -(-88239588111222488472). +-88239588111222488472 = +(-88239588111222488472). +201 = -88239588111222488472 div -437226414144892113. +-357078868099173759 = -88239588111222488472 rem -437226414144892113. +-88671935875773808088 = -88239588111222488472 band -437226414144892113. +-4878649593572497 = -88239588111222488472 bor -437226414144892113. +88667057226180235591 = -88239588111222488472 bxor -437226414144892113. +88239588111222488471 = bnot(-88239588111222488472). +-5647333639118239262208 = -88239588111222488472 bsl 6. +-1378743564237851383 = -88239588111222488472 bsr 6. +-437977443717588881112365 = -437977531113424834577219 + 87395835953464854. +-437977618509260788042073 = -437977531113424834577219 - 87395835953464854. +-38277412460492425885954993823007265561026 = -437977531113424834577219 * 87395835953464854. +437977531113424834577219 = -(-437977531113424834577219). +-437977531113424834577219 = +(-437977531113424834577219). +-5011423 = -437977531113424834577219 div 87395835953464854. +-28712004135549977 = -437977531113424834577219 rem 87395835953464854. +620127049614356 = -437977531113424834577219 band 87395835953464854. +-437977444337715930726721 = -437977531113424834577219 bor 87395835953464854. +-437977444957842980341077 = -437977531113424834577219 bxor 87395835953464854. +437977531113424834577218 = bnot(-437977531113424834577219). +-855424865455907880034 = -437977531113424834577219 bsl -9. +-224244495930073515303536128 = -437977531113424834577219 bsr -9. +57529768662798 = 57529743235679 + 25427119. +57529717808560 = 57529743235679 - 25427119. +1462815627293054978801 = 57529743235679 * 25427119. +-57529743235679 = -(57529743235679). +57529743235679 = +(57529743235679). +2262534 = 57529743235679 div 25427119. +21976133 = 57529743235679 rem 25427119. +25221135 = 57529743235679 band 25427119. +57529743441663 = 57529743235679 bor 25427119. +57529718220528 = 57529743235679 bxor 25427119. +-57529743235680 = bnot(57529743235679). +0 = 57529743235679 bsl -653. +2150203697232589654792902726688504035787373753317740472616158352025532118481145934218614454598229143742728790729735919344159937791585638765207158020340521212411106021591913143080783578332048708490009799261421568 = 57529743235679 bsr -653. +-48168881458034390938 = -48168881457472155651 + -562235287. +-48168881456909920364 = -48168881457472155651 - -562235287. +27082244890710835726948656837 = -48168881457472155651 * -562235287. +48168881457472155651 = -(-48168881457472155651). +-48168881457472155651 = +(-48168881457472155651). +85673885242 = -48168881457472155651 div -562235287. +-31221197 = -48168881457472155651 rem -562235287. +-48168881458025805719 = -48168881457472155651 band -562235287. +-8585219 = -48168881457472155651 bor -562235287. +48168881458017220500 = -48168881457472155651 bxor -562235287. +48168881457472155650 = bnot(-48168881457472155651). +-1 = -48168881457472155651 bsl -581. +-381236121260383005492774074595693584190866122338627672539864171434414087748651811581315483199933807980438282682217386828359838278877913308263353248432527750572413075499014900574630363563558961152 = -48168881457472155651 bsr -581. +739882768287751160101 = 739786335162219961386 + 96433125531198715. +739689902036688762671 = 739786335162219961386 - 96433125531198715. +71339908524963803426561871285592818990 = 739786335162219961386 * 96433125531198715. +-739786335162219961386 = -(739786335162219961386). +739786335162219961386 = +(739786335162219961386). +7671 = 739786335162219961386 div 96433125531198715. +47829212394618621 = 739786335162219961386 rem 96433125531198715. +4512679860372522 = 739786335162219961386 band 96433125531198715. +739878255607890787579 = 739786335162219961386 bor 96433125531198715. +739873742928030415057 = 739786335162219961386 bxor 96433125531198715. +-739786335162219961387 = bnot(739786335162219961386). +0 = 739786335162219961386 bsl -833. +42373339545823064452953060540077710062123552824101456154188513062975916538654414695114452913159036766478308994464946252072164053125988212949097361157966884473506561283361047162159722712646669544255918471902633142986531002304367793320129801334124644819367270027037362880512 = 739786335162219961386 bsr -833. +-625353 = -37665 + -587688. +550023 = -37665 - -587688. +22135268520 = -37665 * -587688. +37665 = -(-37665). +-37665 = +(-37665). +0 = -37665 div -587688. +-37665 = -37665 rem -587688. +-587688 = -37665 band -587688. +-37665 = -37665 bor -587688. +550023 = -37665 bxor -587688. +37664 = bnot(-37665). +-74 = -37665 bsl -9. +-19284480 = -37665 bsr -9. +-26738861699899329205016202072 = -26738861699899323541179316717 + -5663836885355. +-26738861699899317877342431362 = -26738861699899323541179316717 - -5663836885355. +151444551168295885362544490277960363979535 = -26738861699899323541179316717 * -5663836885355. +26738861699899323541179316717 = -(-26738861699899323541179316717). +-26738861699899323541179316717 = +(-26738861699899323541179316717). +4720980183775786 = -26738861699899323541179316717 div -5663836885355. +-259272302687 = -26738861699899323541179316717 rem -5663836885355. +-26738861699899324806125844975 = -26738861699899323541179316717 band -5663836885355. +-4398890357097 = -26738861699899323541179316717 bor -5663836885355. +26738861699899320407235487878 = -26738861699899323541179316717 bxor -5663836885355. +26738861699899323541179316716 = bnot(-26738861699899323541179316717). +-21764540494837285653113708660260658306913102977080703667325446600276054925599603068742626374079187394458447357144933268540651762235834868524509702008202349633834638069722456773697396880298420647631419469270408138078722014103016323178222961281900930669016503419928576 = -26738861699899323541179316717 bsl 787. +-1 = -26738861699899323541179316717 bsr 787. +-64769727830985007813 = -53446138352252 + -64769674384846655561. +64769620938708303309 = -53446138352252 - -64769674384846655561. +3461688978202826803362677532673372 = -53446138352252 * -64769674384846655561. +53446138352252 = -(-53446138352252). +-53446138352252 = +(-53446138352252). +0 = -53446138352252 div -64769674384846655561. +-53446138352252 = -53446138352252 rem -64769674384846655561. +-64769709619149263484 = -53446138352252 band -64769674384846655561. +-18211835744329 = -53446138352252 bor -64769674384846655561. +64769691407313519155 = -53446138352252 bxor -64769674384846655561. +53446138352251 = bnot(-53446138352252). +-459098832640827335901184 = -53446138352252 bsl 33. +-6222 = -53446138352252 bsr 33. +2937974356524398868985611 = 2937974356524398868985294 + 317. +2937974356524398868984977 = 2937974356524398868985294 - 317. +931337871018234441468338198 = 2937974356524398868985294 * 317. +-2937974356524398868985294 = -(2937974356524398868985294). +2937974356524398868985294 = +(2937974356524398868985294). +9268057907017031132445 = 2937974356524398868985294 div 317. +229 = 2937974356524398868985294 rem 317. +268 = 2937974356524398868985294 band 317. +2937974356524398868985343 = 2937974356524398868985294 bor 317. +2937974356524398868985075 = 2937974356524398868985294 bxor 317. +-2937974356524398868985295 = bnot(2937974356524398868985294). +12921347868425151865191655869383704576 = 2937974356524398868985294 bsl 42. +668018027800 = 2937974356524398868985294 bsr 42. +24957774184222492454005 = 741 + 24957774184222492453264. +-24957774184222492452523 = 741 - 24957774184222492453264. +18493710670508866907868624 = 741 * 24957774184222492453264. +-741 = -(741). +741 = +(741). +0 = 741 div 24957774184222492453264. +741 = 741 rem 24957774184222492453264. +128 = 741 band 24957774184222492453264. +24957774184222492453877 = 741 bor 24957774184222492453264. +24957774184222492453749 = 741 bxor 24957774184222492453264. +-742 = bnot(741). +0 = 741 bsl -291. +2948132145437215214697105967014353940115504061926677268987070455022649498290297850159955968 = 741 bsr -291. +-74144284777679928900317788815 = -8444544183 + -74144284777679928891873244632. +74144284777679928883428700449 = -8444544183 - -74144284777679928891873244632. +626114688722052491759721843930491575656 = -8444544183 * -74144284777679928891873244632. +8444544183 = -(-8444544183). +-8444544183 = +(-8444544183). +0 = -8444544183 div -74144284777679928891873244632. +-8444544183 = -8444544183 rem -74144284777679928891873244632. +-74144284777679928895217186296 = -8444544183 band -74144284777679928891873244632. +-5100602519 = -8444544183 bor -74144284777679928891873244632. +74144284777679928890116583777 = -8444544183 bxor -74144284777679928891873244632. +8444544182 = bnot(-8444544183). +-1055568023 = -8444544183 bsl -3. +-67556353464 = -8444544183 bsr -3. +191999140043763205552 = -26334813434414254169 + 218333953478177459721. +-244668766912591713890 = -26334813434414254169 - 218333953478177459721. +-5749783931245884542559171755125253826849 = -26334813434414254169 * 218333953478177459721. +26334813434414254169 = -(-26334813434414254169). +-26334813434414254169 = +(-26334813434414254169). +0 = -26334813434414254169 div 218333953478177459721. +-26334813434414254169 = -26334813434414254169 rem 218333953478177459721. +194881452636271019521 = -26334813434414254169 band 218333953478177459721. +-2882312592507813969 = -26334813434414254169 bor 218333953478177459721. +-197763765228778833490 = -26334813434414254169 bxor 218333953478177459721. +26334813434414254168 = bnot(-26334813434414254169). +-105339253737657016676 = -26334813434414254169 bsl 2. +-6583703358603563543 = -26334813434414254169 bsr 2. +97077970270216582312757580721 = 96665975928744285133262424376 + 411994341472297179495156345. +96253981587271987953767268031 = 96665975928744285133262424376 - 411994341472297179495156345. +39825835095539932495287151918398938981709695283859065720 = 96665975928744285133262424376 * 411994341472297179495156345. +-96665975928744285133262424376 = -(96665975928744285133262424376). +96665975928744285133262424376 = +(96665975928744285133262424376). +234 = 96665975928744285133262424376 div 411994341472297179495156345. +259300024226745131395839646 = 96665975928744285133262424376 rem 411994341472297179495156345. +96752176571981774075594808 = 96665975928744285133262424376 band 411994341472297179495156345. +96981218093644600538681985913 = 96665975928744285133262424376 bor 411994341472297179495156345. +96884465917072618764606391105 = 96665975928744285133262424376 bxor 411994341472297179495156345. +-96665975928744285133262424377 = bnot(96665975928744285133262424376). +6186622459439634248528795160064 = 96665975928744285133262424376 bsl 6. +1510405873886629455207225380 = 96665975928744285133262424376 bsr 6. +669655565377865995388648200720 = 669655565377865995339383557353 + 49264643367. +669655565377865995290118913986 = 669655565377865995339383557353 - 49264643367. +32990342607067320855911215082619335527551 = 669655565377865995339383557353 * 49264643367. +-669655565377865995339383557353 = -(669655565377865995339383557353). +669655565377865995339383557353 = +(669655565377865995339383557353). +13593025740371762130 = 669655565377865995339383557353 div 49264643367. +7577265643 = 669655565377865995339383557353 rem 49264643367. +48593423393 = 669655565377865995339383557353 band 49264643367. +669655565377865995340054777327 = 669655565377865995339383557353 bor 49264643367. +669655565377865995291461353934 = 669655565377865995339383557353 bxor 49264643367. +-669655565377865995339383557354 = bnot(669655565377865995339383557353). +0 = 669655565377865995339383557353 bsl -788. +1090154534911603833409211258660596520018679181593386620841863895484444978620280882365041667806860194849327859281038497075397363173136686064640477233061715543249397573262429774489673948938528155747849665389296215168513071882659601605167905661417721061215192707412000768 = 669655565377865995339383557353 bsr -788. +62680198872129 = 84249394156647 + -21569195284518. +105818589441165 = 84249394156647 - -21569195284518. +-1817191635167048815825891146 = 84249394156647 * -21569195284518. +-84249394156647 = -(84249394156647). +84249394156647 = +(84249394156647). +-3 = 84249394156647 div -21569195284518. +19541808303093 = 84249394156647 rem -21569195284518. +83571591480386 = 84249394156647 band -21569195284518. +-20891392608257 = 84249394156647 bor -21569195284518. +-104462984088643 = 84249394156647 bxor -21569195284518. +-84249394156648 = bnot(84249394156647). +0 = 84249394156647 bsl -385. +6639190301205371846453424945009347141230397653878083794429127533671990806472252090083489931149828497016074919504445953734191611904 = 84249394156647 bsr -385. +8112728482719164532 = 8112728482719164141 + 391. +8112728482719163750 = 8112728482719164141 - 391. +3172076836743193179131 = 8112728482719164141 * 391. +-8112728482719164141 = -(8112728482719164141). +8112728482719164141 = +(8112728482719164141). +20748666196212696 = 8112728482719164141 div 391. +5 = 8112728482719164141 rem 391. +133 = 8112728482719164141 band 391. +8112728482719164399 = 8112728482719164141 bor 391. +8112728482719164266 = 8112728482719164141 bxor 391. +-8112728482719164142 = bnot(8112728482719164141). +63380691271243469 = 8112728482719164141 bsl -7. +1038429245788053010048 = 8112728482719164141 bsr -7. +-667126619869642686 = -667126619869638824 + -3862. +-667126619869634962 = -667126619869638824 - -3862. +2576443005936545138288 = -667126619869638824 * -3862. +667126619869638824 = -(-667126619869638824). +-667126619869638824 = +(-667126619869638824). +172741227309590 = -667126619869638824 div -3862. +-2244 = -667126619869638824 rem -3862. +-667126619869642680 = -667126619869638824 band -3862. +-6 = -667126619869638824 bor -3862. +667126619869642674 = -667126619869638824 bxor -3862. +667126619869638823 = bnot(-667126619869638824). +-5211926717731554 = -667126619869638824 bsl -7. +-85392207343313769472 = -667126619869638824 bsr -7. +-426557362126 = 661597599 + -427218959725. +427880557324 = 661597599 - -427218959725. +-282647038001337700275 = 661597599 * -427218959725. +-661597599 = -(661597599). +661597599 = +(661597599). +0 = 661597599 div -427218959725. +661597599 = 661597599 rem -427218959725. +121897107 = 661597599 band -427218959725. +-426679259233 = 661597599 bor -427218959725. +-426801156340 = 661597599 bxor -427218959725. +-661597600 = bnot(661597599). +42342246336 = 661597599 bsl 6. +10337462 = 661597599 bsr 6. +-6867177441679752363 = 5 + -6867177441679752368. +6867177441679752373 = 5 - -6867177441679752368. +-34335887208398761840 = 5 * -6867177441679752368. +-5 = -(5). +5 = +(5). +0 = 5 div -6867177441679752368. +5 = 5 rem -6867177441679752368. +0 = 5 band -6867177441679752368. +-6867177441679752363 = 5 bor -6867177441679752368. +-6867177441679752363 = 5 bxor -6867177441679752368. +-6 = bnot(5). +2156795733372051183573361206961570453890971553803245798488288819937280 = 5 bsl 228. +0 = 5 bsr 228. +3827466834441551602834674714 = -3685667364298319745 + 3827466838127218967132994459. +-3827466841812886331431314204 = -3685667364298319745 - 3827466838127218967132994459. +-14106769613219570758389934564963414364095292955 = -3685667364298319745 * 3827466838127218967132994459. +3685667364298319745 = -(-3685667364298319745). +-3685667364298319745 = +(-3685667364298319745). +0 = -3685667364298319745 div 3827466838127218967132994459. +-3685667364298319745 = -3685667364298319745 rem 3827466838127218967132994459. +3827466838118178164054104091 = -3685667364298319745 band 3827466838127218967132994459. +-3676626561219429377 = -3685667364298319745 bor 3827466838127218967132994459. +-3827466841794804725273533468 = -3685667364298319745 bxor 3827466838127218967132994459. +3685667364298319744 = bnot(-3685667364298319745). +-16997140652508683198578488716537364480 = -3685667364298319745 bsl 62. +-1 = -3685667364298319745 bsr 62. +-8352846793286413624906528 = 3341361 + -8352846793286413628247889. +8352846793286413631589250 = 3341361 - -8352846793286413628247889. +-27909876514062284327295994636929 = 3341361 * -8352846793286413628247889. +-3341361 = -(3341361). +3341361 = +(3341361). +0 = 3341361 div -8352846793286413628247889. +3341361 = 3341361 rem -8352846793286413628247889. +1208353 = 3341361 band -8352846793286413628247889. +-8352846793286413626114881 = 3341361 bor -8352846793286413628247889. +-8352846793286413627323234 = 3341361 bxor -8352846793286413628247889. +-3341362 = bnot(3341361). +14695461088388972544 = 3341361 bsl 42. +0 = 3341361 bsr 42. +53092 = 53969 + -877. +54846 = 53969 - -877. +-47330813 = 53969 * -877. +-53969 = -(53969). +53969 = +(53969). +-61 = 53969 div -877. +472 = 53969 rem -877. +53393 = 53969 band -877. +-301 = 53969 bor -877. +-53694 = 53969 bxor -877. +-53970 = bnot(53969). +843 = 53969 bsl -6. +3454016 = 53969 bsr -6. +4887551645628250 = -484517 + 4887551646112767. +-4887551646597284 = -484517 - 4887551646112767. +-2368101860919619528539 = -484517 * 4887551646112767. +484517 = -(-484517). +-484517 = +(-484517). +0 = -484517 div 4887551646112767. +-484517 = -484517 rem 4887551646112767. +4887551646112603 = -484517 band 4887551646112767. +-484353 = -484517 bor 4887551646112767. +-4887551646596956 = -484517 bxor 4887551646112767. +484516 = bnot(-484517). +-7571 = -484517 bsl -6. +-31009088 = -484517 bsr -6. +9818661703 = 9818661771 + -68. +9818661839 = 9818661771 - -68. +-667669000428 = 9818661771 * -68. +-9818661771 = -(9818661771). +9818661771 = +(9818661771). +-144392084 = 9818661771 div -68. +59 = 9818661771 rem -68. +9818661768 = 9818661771 band -68. +-65 = 9818661771 bor -68. +-9818661833 = 9818661771 bxor -68. +-9818661772 = bnot(9818661771). +0 = 9818661771 bsl -71. +23183659627001955918025020407808 = 9818661771 bsr -71. +-712255146394710796767561401884 = -712255146394711532165679291249 + 735398117889365. +-712255146394712267563797180614 = -712255146394711532165679291249 - 735398117889365. +-523791094115684997786158104614938540994666885 = -712255146394711532165679291249 * 735398117889365. +712255146394711532165679291249 = -(-712255146394711532165679291249). +-712255146394711532165679291249 = +(-712255146394711532165679291249). +-968530009893042 = -712255146394711532165679291249 div 735398117889365. +-381715239992919 = -712255146394711532165679291249 rem 735398117889365. +572648593671173 = -712255146394711532165679291249 band 735398117889365. +-712255146394711369416155073057 = -712255146394711532165679291249 bor 735398117889365. +-712255146394711942064748744230 = -712255146394711532165679291249 bxor 735398117889365. +712255146394711532165679291248 = bnot(-712255146394711532165679291249). +-4713310 = -712255146394711532165679291249 bsl -77. +-107632954578745541137618349763529320349863629687881728 = -712255146394711532165679291249 bsr -77. +543191318463985309537255 = 543191317734459435141817 + 729525874395438. +543191317004933560746379 = 543191317734459435141817 - 729525874395438. +396272121034241707641659530986667830846 = 543191317734459435141817 * 729525874395438. +-543191317734459435141817 = -(543191317734459435141817). +543191317734459435141817 = +(543191317734459435141817). +744581291 = 543191317734459435141817 div 729525874395438. +359200364591359 = 543191317734459435141817 rem 729525874395438. +158380282873896 = 543191317734459435141817 band 729525874395438. +543191318305605026663359 = 543191317734459435141817 bor 729525874395438. +543191318147224743789463 = 543191317734459435141817 bxor 729525874395438. +-543191317734459435141818 = bnot(543191317734459435141817). +4556619033477828293306127220736 = 543191317734459435141817 bsl 23. +64753451077277593 = 543191317734459435141817 bsr 23. +-169 = -73 + -96. +23 = -73 - -96. +7008 = -73 * -96. +73 = -(-73). +-73 = +(-73). +0 = -73 div -96. +-73 = -73 rem -96. +-96 = -73 band -96. +-73 = -73 bor -96. +23 = -73 bxor -96. +72 = bnot(-73). +-1183260298938720648325803804880682671968392870912882397264386660419600215754462088621791463176322566339993928604003740665292367298847889052639616651915309957638540123626211700113408 = -73 bsl 592. +-1 = -73 bsr 592. +8831173783751346 = 9 + 8831173783751337. +-8831173783751328 = 9 - 8831173783751337. +79480564053762033 = 9 * 8831173783751337. +-9 = -(9). +9 = +(9). +0 = 9 div 8831173783751337. +9 = 9 rem 8831173783751337. +9 = 9 band 8831173783751337. +8831173783751337 = 9 bor 8831173783751337. +8831173783751328 = 9 bxor 8831173783751337. +-10 = bnot(9). +21250649172913403461632 = 9 bsl 71. +0 = 9 bsr 71. +811781846846508316055933 = -8115277375891 + 811781846854623593431824. +-811781846862738870807715 = -8115277375891 - 811781846854623593431824. +-6587834855938339387465949533929755184 = -8115277375891 * 811781846854623593431824. +8115277375891 = -(-8115277375891). +-8115277375891 = +(-8115277375891). +0 = -8115277375891 div 811781846854623593431824. +-8115277375891 = -8115277375891 rem 811781846854623593431824. +811781846848984164991488 = -8115277375891 band 811781846854623593431824. +-2475848935555 = -8115277375891 bor 811781846854623593431824. +-811781846851460013927043 = -8115277375891 bxor 811781846854623593431824. +8115277375890 = bnot(-8115277375891). +-1510015450930589366813802127150545214557626373979929896039337967719857490005174837056015495287940938465420445761003514563307717354269184123213736574976 = -8115277375891 bsl 456. +-1 = -8115277375891 bsr 456. +3753491446477699 = 23456 + 3753491446454243. +-3753491446430787 = 23456 - 3753491446454243. +88041895368030723808 = 23456 * 3753491446454243. +-23456 = -(23456). +23456 = +(23456). +0 = 23456 div 3753491446454243. +23456 = 23456 rem 3753491446454243. +21408 = 23456 band 3753491446454243. +3753491446456291 = 23456 bor 3753491446454243. +3753491446434883 = 23456 bxor 3753491446454243. +-23457 = bnot(23456). +0 = 23456 bsl -444. +1065545569817359701545308702363814647362438234767608276372664631998817196374241355596196080346377387112077856674786216850561725987549085696 = 23456 bsr -444. +17398133890995795 = 21932873413385293 + -4534739522389498. +26467612935774791 = 21932873413385293 - -4534739522389498. +-99459867907244142309416690852914 = 21932873413385293 * -4534739522389498. +-21932873413385293 = -(21932873413385293). +21932873413385293 = +(21932873413385293). +-4 = 21932873413385293 div -4534739522389498. +3793915323827301 = 21932873413385293 rem -4534739522389498. +21923733720815620 = 21932873413385293 band -4534739522389498. +-4525599829819825 = 21932873413385293 bor -4534739522389498. +-26449333550635445 = 21932873413385293 bxor -4534739522389498. +-21932873413385294 = bnot(21932873413385293). +0 = 21932873413385293 bsl -247. +4960260225612245530309503124020715866594788167704014792650628470837551940641670763437359104 = 21932873413385293 bsr -247. +53441059870677 = 54137324433324 + -696264562647. +54833588995971 = 54137324433324 - -696264562647. +-37693900519447081972448628 = 54137324433324 * -696264562647. +-54137324433324 = -(54137324433324). +54137324433324 = +(54137324433324). +-77 = 54137324433324 div -696264562647. +524953109505 = 54137324433324 rem -696264562647. +53999607081000 = 54137324433324 band -696264562647. +-558547210323 = 54137324433324 bor -696264562647. +-54558154291323 = 54137324433324 bxor -696264562647. +-54137324433325 = bnot(54137324433324). +1 = 54137324433324 bsl -45. +1904787766755887616589037568 = 54137324433324 bsr -45. +8257786268962687995 = 8257786268955161814 + 7526181. +8257786268947635633 = 8257786268955161814 - 7526181. +62149594119471228696452334 = 8257786268955161814 * 7526181. +-8257786268955161814 = -(8257786268955161814). +8257786268955161814 = +(8257786268955161814). +1097208035384 = 8257786268955161814 div 7526181. +773310 = 8257786268955161814 rem 7526181. +2266116 = 8257786268955161814 band 7526181. +8257786268960421879 = 8257786268955161814 bor 7526181. +8257786268958155763 = 8257786268955161814 bxor 7526181. +-8257786268955161815 = bnot(8257786268955161814). +2064446567238790453 = 8257786268955161814 bsl -2. +33031145075820647256 = 8257786268955161814 bsr -2. +6852732571801646526 = -33923148 + 6852732571835569674. +-6852732571869492822 = -33923148 - 6852732571835569674. +-232466261238798661715413752 = -33923148 * 6852732571835569674. +33923148 = -(-33923148). +-33923148 = +(-33923148). +0 = -33923148 div 6852732571835569674. +-33923148 = -33923148 rem 6852732571835569674. +6852732571835569664 = -33923148 band 6852732571835569674. +-33923138 = -33923148 bor 6852732571835569674. +-6852732571869492802 = -33923148 bxor 6852732571835569674. +33923147 = bnot(-33923148). +-21782271568400745073903219172783846555237631662776043049986741799362091680002283776431101407811523695564419536863711473859250454968134546588361401779957252264574810298924994276642619876092046681855009415287374086144 = -33923148 bsl 687. +-1 = -33923148 bsr 687. +4933596866441911751760609356 = -87768791 + 4933596866441911751848378147. +-4933596866441911751936146938 = -87768791 - 4933596866441911751848378147. +-433015832248995066188424165273010277 = -87768791 * 4933596866441911751848378147. +87768791 = -(-87768791). +-87768791 = +(-87768791). +0 = -87768791 div 4933596866441911751848378147. +-87768791 = -87768791 rem 4933596866441911751848378147. +4933596866441911751848231201 = -87768791 band 4933596866441911751848378147. +-87621845 = -87768791 bor 4933596866441911751848378147. +-4933596866441911751935853046 = -87768791 bxor 4933596866441911751848378147. +87768790 = bnot(-87768791). +-1 = -87768791 bsl -823. +-4909378852518964665397930710056376487208812040153826207402671768865531237643441262508997952270996583077595683649423749336461411177429052678292244331311794729913386285051361522165088879213446951378294299353770172247965285722703217125354394092893822599036928 = -87768791 bsr -823. +8741864586305876256 = 8741864585723676465 + 582199791. +8741864585141476674 = 8741864585723676465 - 582199791. +5089511734758626021674618815 = 8741864585723676465 * 582199791. +-8741864585723676465 = -(8741864585723676465). +8741864585723676465 = +(8741864585723676465). +15015231404 = 8741864585723676465 div 582199791. +498239901 = 8741864585723676465 rem 582199791. +580944161 = 8741864585723676465 band 582199791. +8741864585724932095 = 8741864585723676465 bor 582199791. +8741864585143987934 = 8741864585723676465 bxor 582199791. +-8741864585723676466 = bnot(8741864585723676465). +0 = 8741864585723676465 bsl -72. +41282288317406626147881407260211690864640 = 8741864585723676465 bsr -72. +-26994448456349269779196434055 = -995853541223 + -26994448456349268783342892832. +26994448456349267787489351609 = -995853541223 - -26994448456349268783342892832. +26882517088617165256418668582616183213536 = -995853541223 * -26994448456349268783342892832. +995853541223 = -(-995853541223). +-995853541223 = +(-995853541223). +0 = -995853541223 div -26994448456349268783342892832. +-995853541223 = -995853541223 rem -26994448456349268783342892832. +-26994448456349269615645245312 = -995853541223 band -26994448456349268783342892832. +-163551188743 = -995853541223 bor -26994448456349268783342892832. +26994448456349269452094056569 = -995853541223 bxor -26994448456349268783342892832. +995853541222 = bnot(-995853541223). +-1 = -995853541223 bsl -219. +-839004948739536910209664142641239584601848226954266016490647922432867223732224 = -995853541223 bsr -219. +7478630468 = -248785 + 7478879253. +-7479128038 = -248785 - 7478879253. +-1860632974957605 = -248785 * 7478879253. +248785 = -(-248785). +-248785 = +(-248785). +0 = -248785 div 7478879253. +-248785 = -248785 rem 7478879253. +7478715397 = -248785 band 7478879253. +-84929 = -248785 bor 7478879253. +-7478800326 = -248785 bxor 7478879253. +248784 = bnot(-248785). +-1 = -248785 bsl -88. +-76995228168403332922694655016960 = -248785 bsr -88. +9112624 = 9112626 + -2. +9112628 = 9112626 - -2. +-18225252 = 9112626 * -2. +-9112626 = -(9112626). +9112626 = +(9112626). +-4556313 = 9112626 div -2. +0 = 9112626 rem -2. +9112626 = 9112626 band -2. +-2 = 9112626 bor -2. +-9112628 = 9112626 bxor -2. +-9112627 = bnot(9112626). +0 = 9112626 bsl -87. +1410110573554122214116613347606528 = 9112626 bsr -87. +-9231217449626140093169195 = 7158295958 + -9231217449626147251465153. +9231217449626154409761111 = 7158295958 - -9231217449626147251465153. +-66079786557077918481275814297751574 = 7158295958 * -9231217449626147251465153. +-7158295958 = -(7158295958). +7158295958 = +(7158295958). +0 = 7158295958 div -9231217449626147251465153. +7158295958 = 7158295958 rem -9231217449626147251465153. +4431299606 = 7158295958 band -9231217449626147251465153. +-9231217449626144524468801 = 7158295958 bor -9231217449626147251465153. +-9231217449626148955768407 = 7158295958 bxor -9231217449626147251465153. +-7158295959 = bnot(7158295958). +13981046 = 7158295958 bsl -9. +3665047530496 = 7158295958 bsr -9. +733622196575874592956977683677 = 733622196575874592956977683719 + -42. +733622196575874592956977683761 = 733622196575874592956977683719 - -42. +-30812132256186732904193062716198 = 733622196575874592956977683719 * -42. +-733622196575874592956977683719 = -(733622196575874592956977683719). +733622196575874592956977683719 = +(733622196575874592956977683719). +-17467195156568442689451849612 = 733622196575874592956977683719 div -42. +15 = 733622196575874592956977683719 rem -42. +733622196575874592956977683718 = 733622196575874592956977683719 band -42. +-41 = 733622196575874592956977683719 bor -42. +-733622196575874592956977683759 = 733622196575874592956977683719 bxor -42. +-733622196575874592956977683720 = bnot(733622196575874592956977683719). +0 = 733622196575874592956977683719 bsl -982. +29986667558820548860569388339118939628021609752472298746240482499913429520272515420974508069522157046073722363662951409931227880373184804148721237710463162469842938171830741413264701323225102429378796617204756120261640476470840409010032421701834204666551977915902768691582481649109164531815901034693474889878223588005223858176 = 733622196575874592956977683719 bsr -982. +811349291315272899466 = 811349291315272899411 + 55. +811349291315272899356 = 811349291315272899411 - 55. +44624211022340009467605 = 811349291315272899411 * 55. +-811349291315272899411 = -(811349291315272899411). +811349291315272899411 = +(811349291315272899411). +14751805296641325443 = 811349291315272899411 div 55. +46 = 811349291315272899411 rem 55. +19 = 811349291315272899411 band 55. +811349291315272899447 = 811349291315272899411 bor 55. +811349291315272899428 = 811349291315272899411 bxor 55. +-811349291315272899412 = bnot(811349291315272899411). +1124801795688128809117845354257026935140522772168575758953903827993679735658665042098288387621672886911021174779684507191627912556218392869482195320832 = 811349291315272899411 bsl 429. +0 = 811349291315272899411 bsr 429. +885975861442819814306863 = 885975861442819814297548 + 9315. +885975861442819814288233 = 885975861442819814297548 - 9315. +8252865149339866570181659620 = 885975861442819814297548 * 9315. +-885975861442819814297548 = -(885975861442819814297548). +885975861442819814297548 = +(885975861442819814297548). +95112813896169598958 = 885975861442819814297548 div 9315. +3778 = 885975861442819814297548 rem 9315. +1088 = 885975861442819814297548 band 9315. +885975861442819814305775 = 885975861442819814297548 bor 9315. +885975861442819814304687 = 885975861442819814297548 bxor 9315. +-885975861442819814297549 = bnot(885975861442819814297548). +0 = 885975861442819814297548 bsl -927. +1005143040823854522478619626628497929067403976849016345635161191003470159625580516200556688949945723013240038033686213398765835282099300420928799390266566436852158165277864040471010072625095701590737584910653891758231878828261163348792412956637359318013736327093066282518636197068463689890831796424146944 = 885975861442819814297548 bsr -927. +41399875836504791656137563799 = 41399875836262823738481646965 + 241967917655916834. +41399875836020855820825730131 = 41399875836262823738481646965 - 241967917655916834. +10017441747314024011053170597295347749388508810 = 41399875836262823738481646965 * 241967917655916834. +-41399875836262823738481646965 = -(41399875836262823738481646965). +41399875836262823738481646965 = +(41399875836262823738481646965). +171096549647 = 41399875836262823738481646965 div 241967917655916834. +66041286697589367 = 41399875836262823738481646965 rem 241967917655916834. +72339653133074720 = 41399875836262823738481646965 band 241967917655916834. +41399875836432452003004489079 = 41399875836262823738481646965 bor 241967917655916834. +41399875836360112349871414359 = 41399875836262823738481646965 bxor 241967917655916834. +-41399875836262823738481646966 = bnot(41399875836262823738481646965). +71817336515 = 41399875836262823738481646965 bsl -59. +23865403569840390970934364411101718826104913920 = 41399875836262823738481646965 bsr -59. +4274843908092340195 = -4185377341 + 4274843912277717536. +-4274843916463094877 = -4185377341 - 4274843912277717536. +-17891834846758950674372751776 = -4185377341 * 4274843912277717536. +4185377341 = -(-4185377341). +-4185377341 = +(-4185377341). +0 = -4185377341 div 4274843912277717536. +-4185377341 = -4185377341 rem 4274843912277717536. +4274843909710426112 = -4185377341 band 4274843912277717536. +-1618085917 = -4185377341 bor 4274843912277717536. +-4274843911328512029 = -4185377341 bxor 4274843912277717536. +4185377340 = bnot(-4185377341). +-1295311547485420108782786396968452096 = -4185377341 bsl 88. +-1 = -4185377341 bsr 88. +-6242811754787962 = -6242811754788576 + 614. +-6242811754789190 = -6242811754788576 - 614. +-3833086417440185664 = -6242811754788576 * 614. +6242811754788576 = -(-6242811754788576). +-6242811754788576 = +(-6242811754788576). +-10167445854704 = -6242811754788576 div 614. +-320 = -6242811754788576 rem 614. +32 = -6242811754788576 band 614. +-6242811754787994 = -6242811754788576 bor 614. +-6242811754788026 = -6242811754788576 bxor 614. +6242811754788575 = bnot(-6242811754788576). +-97543933668572 = -6242811754788576 bsl -6. +-399539952306468864 = -6242811754788576 bsr -6. +-7538171139905556212306216 = -7629586458271768482155827 + 91415318366212269849611. +-7721001776637980752005438 = -7629586458271768482155827 - 91415318366212269849611. +-697461075085455621116210985649692909134357333297 = -7629586458271768482155827 * 91415318366212269849611. +7629586458271768482155827 = -(-7629586458271768482155827). +-7629586458271768482155827 = +(-7629586458271768482155827). +-83 = -7629586458271768482155827 div 91415318366212269849611. +-42115033876150084638114 = -7629586458271768482155827 rem 91415318366212269849611. +77236661554355152924681 = -7629586458271768482155827 band 91415318366212269849611. +-7615407801459911365230897 = -7629586458271768482155827 bor 91415318366212269849611. +-7692644463014266518155578 = -7629586458271768482155827 bxor 91415318366212269849611. +7629586458271768482155826 = bnot(-7629586458271768482155827). +-3469534230259 = -7629586458271768482155827 bsl -41. +-16777638051984237727202732308906901504 = -7629586458271768482155827 bsr -41. +-4267121652459075945934652272 = -4267121648737814333378672448 + -3721261612555979824. +-4267121645016552720822692624 = -4267121648737814333378672448 - -3721261612555979824. +15879075987554610274837263875481017808992689152 = -4267121648737814333378672448 * -3721261612555979824. +4267121648737814333378672448 = -(-4267121648737814333378672448). +-4267121648737814333378672448 = +(-4267121648737814333378672448). +1146686821 = -4267121648737814333378672448 div -3721261612555979824. +-126664144455972944 = -4267121648737814333378672448 rem -3721261612555979824. +-4267121651089823294832672576 = -4267121648737814333378672448 band -3721261612555979824. +-1369252651101979696 = -4267121648737814333378672448 bor -3721261612555979824. +4267121649720570643730692880 = -4267121648737814333378672448 bxor -3721261612555979824. +4267121648737814333378672447 = bnot(-4267121648737814333378672448). +-1 = -4267121648737814333378672448 bsl -651. +-39871465739338534063342663826501196000324697659784107528606747974331669942608986453404016148280232658289099588827686503977278355928542987546437376620656531497244946319740519491056964833008916902911927004689951702106037551104 = -4267121648737814333378672448 bsr -651. +-4036400470114176 = -4273587136568859 + 237186666454683. +-4510773803023542 = -4273587136568859 - 237186666454683. +-1013637886726381765650632516697 = -4273587136568859 * 237186666454683. +4273587136568859 = -(-4273587136568859). +-4273587136568859 = +(-4273587136568859). +-18 = -4273587136568859 div 237186666454683. +-4227140384565 = -4273587136568859 rem 237186666454683. +230005444362369 = -4273587136568859 band 237186666454683. +-4266405914476545 = -4273587136568859 bor 237186666454683. +-4496411358838914 = -4273587136568859 bxor 237186666454683. +4273587136568858 = bnot(-4273587136568859). +-1 = -4273587136568859 bsl -92. +-21161778510934196433939532476604893483761664 = -4273587136568859 bsr -92. +-91484855776220637360611 = 596954114912 + -91484855776817591475523. +91484855777414545590435 = 596954114912 - -91484855776817591475523. +-54612261108102115527342428577298976 = 596954114912 * -91484855776817591475523. +-596954114912 = -(596954114912). +596954114912 = +(596954114912). +0 = 596954114912 div -91484855776817591475523. +596954114912 = 596954114912 rem -91484855776817591475523. +558882628128 = 596954114912 band -91484855776817591475523. +-91484855776779519988739 = 596954114912 bor -91484855776817591475523. +-91484855777338402616867 = 596954114912 bxor -91484855776817591475523. +-596954114913 = bnot(596954114912). +2503807031991861248 = 596954114912 bsl 22. +142324 = 596954114912 bsr 22. +65569748663986084 = -4498113 + 65569748668484197. +-65569748672982310 = -4498113 - 65569748668484197. +-294940138892441456820261 = -4498113 * 65569748668484197. +4498113 = -(-4498113). +-4498113 = +(-4498113). +0 = -4498113 div 65569748668484197. +-4498113 = -4498113 rem 65569748668484197. +65569748663994405 = -4498113 band 65569748668484197. +-8321 = -4498113 bor 65569748668484197. +-65569748664002726 = -4498113 bxor 65569748668484197. +4498112 = bnot(-4498113). +-178188613885762551182954379538857984 = -4498113 bsl 95. +-1 = -4498113 bsr 95. +-777223525640658 = -777223525611319 + -29339. +-777223525581980 = -777223525611319 - -29339. +22802961017910488141 = -777223525611319 * -29339. +777223525611319 = -(-777223525611319). +-777223525611319 = +(-777223525611319). +26491138948 = -777223525611319 div -29339. +-15947 = -777223525611319 rem -29339. +-777223525627839 = -777223525611319 band -29339. +-12819 = -777223525611319 bor -29339. +777223525615020 = -777223525611319 bxor -29339. +777223525611318 = bnot(-777223525611319). +-198969222556497664 = -777223525611319 bsl 8. +-3036029396920 = -777223525611319 bsr 8. +96417343 = 97244955 + -827612. +98072567 = 97244955 - -827612. +-80481091697460 = 97244955 * -827612. +-97244955 = -(97244955). +97244955 = +(97244955). +-117 = 97244955 div -827612. +414351 = 97244955 rem -827612. +96687872 = 97244955 band -827612. +-270529 = 97244955 bor -827612. +-96958401 = 97244955 bxor -827612. +-97244956 = bnot(97244955). +0 = 97244955 bsl -881. +1567809384369929985858068741727183110280701137458891778377229107393402021905611996672699880982016244270146370873154137628391215170843459394808333944286332041143039007815016768028549464218926813385360539034073368739559839619975355452669118002097778858629874794621716041564160 = 97244955 bsr -881. +3198551991723789764315794183 = 3198551987886863514642434571 + 3836926249673359612. +3198551984049937264969074959 = 3198551987886863514642434571 - 3836926249673359612. +12272608083268012387137280170851540240463946452 = 3198551987886863514642434571 * 3836926249673359612. +-3198551987886863514642434571 = -(3198551987886863514642434571). +3198551987886863514642434571 = +(3198551987886863514642434571). +833623525 = 3198551987886863514642434571 div 3836926249673359612. +2469127376294362271 = 3198551987886863514642434571 rem 3836926249673359612. +3758253958181683208 = 3198551987886863514642434571 band 3836926249673359612. +3198551987965535806134110975 = 3198551987886863514642434571 bor 3836926249673359612. +3198551984207281847952427767 = 3198551987886863514642434571 bxor 3836926249673359612. +-3198551987886863514642434572 = bnot(3198551987886863514642434571). +173393850 = 3198551987886863514642434571 bsl -64. +59002869927003905065155415068870526795027316736 = 3198551987886863514642434571 bsr -64. +-439573608517099225018102502 = 47624424382333611295892 + -439621232941481558629398394. +439668857365863892240694286 = 47624424382333611295892 - -439621232941481558629398394. +-20936708165089858529216529838982016081590683597448 = 47624424382333611295892 * -439621232941481558629398394. +-47624424382333611295892 = -(47624424382333611295892). +47624424382333611295892 = +(47624424382333611295892). +0 = 47624424382333611295892 div -439621232941481558629398394. +47624424382333611295892 = 47624424382333611295892 rem -439621232941481558629398394. +47614587867083402395780 = 47624424382333611295892 band -439621232941481558629398394. +-439621223104966308420498282 = 47624424382333611295892 bor -439621232941481558629398394. +-439668837692833391822894062 = 47624424382333611295892 bxor -439621232941481558629398394. +-47624424382333611295893 = bnot(47624424382333611295892). +5953053047791701411986 = 47624424382333611295892 bsl -3. +380995395058668890367136 = 47624424382333611295892 bsr -3. +-89689944725641365990750893772 = -89688946256488841397951674395 + -998469152524592799219377. +-89687947787336316805152455018 = -89688946256488841397951674395 - -998469152524592799219377. +89551646159540163343803048054284057336968126078751915 = -89688946256488841397951674395 * -998469152524592799219377. +89688946256488841397951674395 = -(-89688946256488841397951674395). +-89688946256488841397951674395 = +(-89688946256488841397951674395). +89826 = -89688946256488841397951674395 div -998469152524592799219377. +-456161814768615271915993 = -89688946256488841397951674395 rem -998469152524592799219377. +-89688957491206761847796203195 = -89688946256488841397951674395 band -998469152524592799219377. +-987234434604142954690577 = -89688946256488841397951674395 bor -998469152524592799219377. +89687970256772157704841512618 = -89688946256488841397951674395 bxor -998469152524592799219377. +89688946256488841397951674394 = bnot(-89688946256488841397951674395). +-1577824628671779641725474254499699039928320 = -89688946256488841397951674395 bsl 44. +-5098226339242095 = -89688946256488841397951674395 bsr 44. +-107944578653 = -7956649228 + -99987929425. +92031280197 = -7956649228 - -99987929425. +795568881468744733900 = -7956649228 * -99987929425. +7956649228 = -(-7956649228). +-7956649228 = +(-7956649228). +0 = -7956649228 div -99987929425. +-7956649228 = -7956649228 rem -99987929425. +-102542277980 = -7956649228 band -99987929425. +-5402300673 = -7956649228 bor -99987929425. +97139977307 = -7956649228 bxor -99987929425. +7956649227 = bnot(-7956649228). +-124322645 = -7956649228 bsl -6. +-509225550592 = -7956649228 bsr -6. +-51547258647535796118556002179 = -51547258555743582681958687423 + -91792213436597314756. +-51547258463951369245361372667 = -51547258555743582681958687423 - -91792213436597314756. +4731636959420281983396358032954664794408149513788 = -51547258555743582681958687423 * -91792213436597314756. +51547258555743582681958687423 = -(-51547258555743582681958687423). +-51547258555743582681958687423 = +(-51547258555743582681958687423). +561564610 = -51547258555743582681958687423 div -91792213436597314756. +-16184051893958302263 = -51547258555743582681958687423 rem -91792213436597314756. +-51547258563298109923031492352 = -51547258555743582681958687423 band -91792213436597314756. +-84237686195524509827 = -51547258555743582681958687423 bor -91792213436597314756. +51547258479060423727506982525 = -51547258555743582681958687423 bxor -91792213436597314756. +51547258555743582681958687422 = bnot(-51547258555743582681958687423). +-206189034222974330727834749692 = -51547258555743582681958687423 bsl 2. +-12886814638935895670489671856 = -51547258555743582681958687423 bsr 2. +-224891864892188194404827 = -75871363 + -224891864892188118533464. +224891864892188042662101 = -75871363 - -224891864892188118533464. +17062852316982160605539474791432 = -75871363 * -224891864892188118533464. +75871363 = -(-75871363). +-75871363 = +(-75871363). +0 = -75871363 div -224891864892188118533464. +-75871363 = -75871363 rem -224891864892188118533464. +-224891864892188118611416 = -75871363 band -224891864892188118533464. +-75793411 = -75871363 bor -224891864892188118533464. +224891864892188042818005 = -75871363 bxor -224891864892188118533464. +75871362 = bnot(-75871363). +-14456257168929956743916818538905745587330375758255603855674002658551814160518532039738027833047217492154099127703139584735390894188138005134344978432 = -75871363 bsl 466. +-1 = -75871363 bsr 466. +-92626589181922614192054168450 = -92626589178671292863737413479 + -3251321328316754971. +-92626589175419971535420658508 = -92626589178671292863737413479 - -3251321328316754971. +301158804965847909758322589425413031470155654109 = -92626589178671292863737413479 * -3251321328316754971. +92626589178671292863737413479 = -(-92626589178671292863737413479). +-92626589178671292863737413479 = +(-92626589178671292863737413479). +28488906455 = -92626589178671292863737413479 div -3251321328316754971. +-1108917885762175674 = -92626589178671292863737413479 rem -3251321328316754971. +-92626589180980516345207242623 = -92626589178671292863737413479 band -3251321328316754971. +-942097846846925827 = -92626589178671292863737413479 bor -3251321328316754971. +92626589180038418498360316796 = -92626589178671292863737413479 bxor -3251321328316754971. +92626589178671292863737413478 = bnot(-92626589178671292863737413479). +-21566308377932592497 = -92626589178671292863737413479 bsl -32. +-397828171262420703583790375223934582784 = -92626589178671292863737413479 bsr -32. +81117343425000610841 = 81117343429423544534 + -4422933693. +81117343433846478227 = 81117343429423544534 - -4422933693. +-358776631340649562686914584062 = 81117343429423544534 * -4422933693. +-81117343429423544534 = -(81117343429423544534). +81117343429423544534 = +(81117343429423544534). +-18340167196 = 81117343429423544534 div -4422933693. +2981809706 = 81117343429423544534 rem -4422933693. +81117343429387886658 = 81117343429423544534 band -4422933693. +-4387275817 = 81117343429423544534 bor -4422933693. +-81117343433775162475 = 81117343429423544534 bxor -4422933693. +-81117343429423544535 = bnot(81117343429423544534). +0 = 81117343429423544534 bsl -75. +3064526590324287910001030154146913621901312 = 81117343429423544534 bsr -75. +2289828191515276228 = 897 + 2289828191515275331. +-2289828191515274434 = 897 - 2289828191515275331. +2053975887789201971907 = 897 * 2289828191515275331. +-897 = -(897). +897 = +(897). +0 = 897 div 2289828191515275331. +897 = 897 rem 2289828191515275331. +1 = 897 band 2289828191515275331. +2289828191515276227 = 897 bor 2289828191515275331. +2289828191515276226 = 897 bxor 2289828191515275331. +-898 = bnot(897). +0 = 897 bsl -77. +135550807524290296213929984 = 897 bsr -77. +9192773900209659062759187325 = 8917952238734891769776674856 + 274821661474767292982512469. +8643130577260124476794162387 = 8917952238734891769776674856 - 274821661474767292982512469. +2450846451201743538156756726936311131318670343378779464 = 8917952238734891769776674856 * 274821661474767292982512469. +-8917952238734891769776674856 = -(8917952238734891769776674856). +8917952238734891769776674856 = +(8917952238734891769776674856). +32 = 8917952238734891769776674856 div 274821661474767292982512469. +123659071542338394336275848 = 8917952238734891769776674856 rem 274821661474767292982512469. +232424254142200712549107712 = 8917952238734891769776674856 band 274821661474767292982512469. +8960349646067458350210079613 = 8917952238734891769776674856 bor 274821661474767292982512469. +8727925391925257637660971901 = 8917952238734891769776674856 bxor 274821661474767292982512469. +-8917952238734891769776674857 = bnot(8917952238734891769776674856). +0 = 8917952238734891769776674856 bsl -584. +564654261126213671114483452323326413544879874913914808333671107414843491072816921551217451075660814076529724813634685375060836733551015518497888460292811462963241339175888195957918257118982987786271850496 = 8917952238734891769776674856 bsr -584. +584763 = 427 + 584336. +-583909 = 427 - 584336. +249511472 = 427 * 584336. +-427 = -(427). +427 = +(427). +0 = 427 div 584336. +427 = 427 rem 584336. +128 = 427 band 584336. +584635 = 427 bor 584336. +584507 = 427 bxor 584336. +-428 = bnot(427). +4228803174198859019055408349184 = 427 bsl 93. +0 = 427 bsr 93. +2873569340219161220 = 7391242189536 + 2873561948976971684. +-2873554557734782148 = 7391242189536 - 2873561948976971684. +21239192311523887704890833098624 = 7391242189536 * 2873561948976971684. +-7391242189536 = -(7391242189536). +7391242189536 = +(7391242189536). +0 = 7391242189536 div 2873561948976971684. +7391242189536 = 7391242189536 rem 2873561948976971684. +103756167840 = 7391242189536 band 2873561948976971684. +2873569236462993380 = 7391242189536 bor 2873561948976971684. +2873569132706825540 = 7391242189536 bxor 2873561948976971684. +-7391242189537 = bnot(7391242189536). +17043044132146902307495080886272 = 7391242189536 bsl 61. +0 = 7391242189536 bsr 61. +73238685419183094543 = -3683395 + 73238685419186777938. +-73238685419190461333 = -3683395 - 73238685419186777938. +-269767007679605481922939510 = -3683395 * 73238685419186777938. +3683395 = -(-3683395). +-3683395 = +(-3683395). +0 = -3683395 div 73238685419186777938. +-3683395 = -3683395 rem 73238685419186777938. +73238685419183622928 = -3683395 band 73238685419186777938. +-528385 = -3683395 bor 73238685419186777938. +-73238685419184151313 = -3683395 bxor 73238685419186777938. +3683394 = bnot(-3683395). +-1 = -3683395 bsl -844. +-432080467963048262555853318747661237135491073876285524679401425413095676321779140263983609193746870415010306742107002773190381670106317989361810254628326460421320780438073712482013284075623886968942998082030670994745774987273376488656463788581076528831733432320 = -3683395 bsr -844. +92722951385418647291709 = 558134 + 92722951385418646733575. +-92722951385418646175441 = 558134 - 92722951385418646733575. +51751831748549250975997149050 = 558134 * 92722951385418646733575. +-558134 = -(558134). +558134 = +(558134). +0 = 558134 div 92722951385418646733575. +558134 = 558134 rem 92722951385418646733575. +32774 = 558134 band 92722951385418646733575. +92722951385418647258935 = 558134 bor 92722951385418646733575. +92722951385418647226161 = 558134 bxor 92722951385418646733575. +-558135 = bnot(558134). +321742345526118965051392 = 558134 bsl 59. +0 = 558134 bsr 59. +-63546419921881191 = -497245399 + -63546419424635792. +63546418927390393 = -497245399 - -63546419424635792. +31598164681824374822721008 = -497245399 * -63546419424635792. +497245399 = -(-497245399). +-497245399 = +(-497245399). +0 = -497245399 div -63546419424635792. +-497245399 = -497245399 rem -63546419424635792. +-63546419443662816 = -497245399 band -63546419424635792. +-478218375 = -497245399 bor -63546419424635792. +63546418965444441 = -497245399 bxor -63546419424635792. +497245398 = bnot(-497245399). +-1942365 = -497245399 bsl -8. +-127294822144 = -497245399 bsr -8. +-35008318338433879811771391803 = -34379533892997313329548513238 + -628784445436566482222878565. +-33750749447560746847325634673 = -34379533892997313329548513238 - -628784445436566482222878565. +21617316153275957220539326692103788726389233444368943470 = -34379533892997313329548513238 * -628784445436566482222878565. +34379533892997313329548513238 = -(-34379533892997313329548513238). +-34379533892997313329548513238 = +(-34379533892997313329548513238). +54 = -34379533892997313329548513238 div -628784445436566482222878565. +-425173839422723289513070728 = -34379533892997313329548513238 rem -628784445436566482222878565. +-34389252543110051313847685110 = -34379533892997313329548513238 band -628784445436566482222878565. +-619065795323828497923706693 = -34379533892997313329548513238 bor -628784445436566482222878565. +33770186747786222815923978417 = -34379533892997313329548513238 bxor -628784445436566482222878565. +34379533892997313329548513237 = bnot(-34379533892997313329548513238). +-8196719620942428905857 = -34379533892997313329548513238 bsl -22. +-144198216525534203287378647268196352 = -34379533892997313329548513238 bsr -22. +-94420 = 545 + -94965. +95510 = 545 - -94965. +-51755925 = 545 * -94965. +-545 = -(545). +545 = +(545). +0 = 545 div -94965. +545 = 545 rem -94965. +1 = 545 band -94965. +-94421 = 545 bor -94965. +-94422 = 545 bxor -94965. +-546 = bnot(545). +0 = 545 bsl -44. +9587741394206720 = 545 bsr -44. +2795644593395452536265 = 2795644593395373913827 + 78622438. +2795644593395295291389 = 2795644593395373913827 - 78622438. +219800393714262995026680650226 = 2795644593395373913827 * 78622438. +-2795644593395373913827 = -(2795644593395373913827). +2795644593395373913827 = +(2795644593395373913827). +35557846646721 = 2795644593395373913827 div 78622438. +44188029 = 2795644593395373913827 rem 78622438. +76490466 = 2795644593395373913827 band 78622438. +2795644593395376045799 = 2795644593395373913827 bor 78622438. +2795644593395299555333 = 2795644593395373913827 bxor 78622438. +-2795644593395373913828 = bnot(2795644593395373913827). +698911148348843478456 = 2795644593395373913827 bsl -2. +11182578373581495655308 = 2795644593395373913827 bsr -2. +-8787568974423759098778 = -8787568974423759158612 + 59834. +-8787568974423759218446 = -8787568974423759158612 - 59834. +-525795402015671205496390408 = -8787568974423759158612 * 59834. +8787568974423759158612 = -(-8787568974423759158612). +-8787568974423759158612 = +(-8787568974423759158612). +-146865811652634942 = -8787568974423759158612 div 59834. +-38984 = -8787568974423759158612 rem 59834. +32936 = -8787568974423759158612 band 59834. +-8787568974423759131714 = -8787568974423759158612 bor 59834. +-8787568974423759164650 = -8787568974423759158612 bxor 59834. +8787568974423759158611 = bnot(-8787568974423759158612). +-1 = -8787568974423759158612 bsl -579. +-17387463699334606574369673082096282686305542007575594251570474477704968929224742151269560686612629435515287574348276272141023568588788324161754188375467588140470398322054786885776003241773530873856 = -8787568974423759158612 bsr -579. +-44295264476766669313925 = 2264128488185265259789 + -46559392964951934573714. +48823521453137199833503 = 2264128488185265259789 - -46559392964951934573714. +-105416448004560298652327962495129255180586346 = 2264128488185265259789 * -46559392964951934573714. +-2264128488185265259789 = -(2264128488185265259789). +2264128488185265259789 = +(2264128488185265259789). +0 = 2264128488185265259789 div -46559392964951934573714. +2264128488185265259789 = 2264128488185265259789 rem -46559392964951934573714. +590302565758291542284 = 2264128488185265259789 band -46559392964951934573714. +-44885567042524960856209 = 2264128488185265259789 bor -46559392964951934573714. +-45475869608283252398493 = 2264128488185265259789 bxor -46559392964951934573714. +-2264128488185265259790 = bnot(2264128488185265259789). +35377007627894769684 = 2264128488185265259789 bsl -6. +144904223243856976626496 = 2264128488185265259789 bsr -6. +-61546169223333011082 = -61546169215361312324 + -7971698758. +-61546169207389613566 = -61546169215361312324 - -7971698758. +490627520693753607974480893592 = -61546169215361312324 * -7971698758. +61546169215361312324 = -(-61546169215361312324). +-61546169215361312324 = +(-61546169215361312324). +7720583916 = -61546169215361312324 div -7971698758. +-1149335996 = -61546169215361312324 rem -7971698758. +-61546169219790896712 = -61546169215361312324 band -7971698758. +-3542114370 = -61546169215361312324 bor -7971698758. +61546169216248782342 = -61546169215361312324 bxor -7971698758. +61546169215361312323 = bnot(-61546169215361312324). +-121777909929335523574588157034445100959831387059408680082411440556553243672720190039604708970499490782835119930156702044709277648871091652309490418630295508362600151076627660779355865587239616512 = -61546169215361312324 bsl 579. +-1 = -61546169215361312324 bsr 579. +23649639883984821896606 = 23649639883984817244112 + 4652494. +23649639883984812591618 = 23649639883984817244112 - 4652494. +110029807662400058319327615328 = 23649639883984817244112 * 4652494. +-23649639883984817244112 = -(23649639883984817244112). +23649639883984817244112 = +(23649639883984817244112). +5083217707316724 = 23649639883984817244112 div 4652494. +2734456 = 23649639883984817244112 rem 4652494. +4343232 = 23649639883984817244112 band 4652494. +23649639883984817553374 = 23649639883984817244112 bor 4652494. +23649639883984813210142 = 23649639883984817244112 bxor 4652494. +-23649639883984817244113 = bnot(23649639883984817244112). +175260237560112780376561341239759785667109378118687222490628883487671117225086117574386608280067637248 = 23649639883984817244112 bsl 262. +0 = 23649639883984817244112 bsr 262. +86829374765368359338103465 = -7856119756 + 86829374765368367194223221. +-86829374765368375050342977 = -7856119756 - 86829374765368367194223221. +-682141966495338294131999335572054076 = -7856119756 * 86829374765368367194223221. +7856119756 = -(-7856119756). +-7856119756 = +(-7856119756). +0 = -7856119756 div 86829374765368367194223221. +-7856119756 = -7856119756 rem 86829374765368367194223221. +86829374765368366858510388 = -7856119756 band 86829374765368367194223221. +-7520406923 = -7856119756 bor 86829374765368367194223221. +-86829374765368374378917311 = -7856119756 bxor 86829374765368367194223221. +7856119755 = bnot(-7856119756). +-982014970 = -7856119756 bsl -3. +-62848958048 = -7856119756 bsr -3. +362130164919076 = 522657498 + 362129642261578. +-362129119604080 = 522657498 - 362129642261578. +189269772776071419011844 = 522657498 * 362129642261578. +-522657498 = -(522657498). +522657498 = +(522657498). +0 = 522657498 div 362129642261578. +522657498 = 522657498 rem 362129642261578. +2100298 = 522657498 band 362129642261578. +362130162818778 = 522657498 bor 362129642261578. +362130160718480 = 522657498 bxor 362129642261578. +-522657499 = bnot(522657498). +65332187 = 522657498 bsl -3. +4181259984 = 522657498 bsr -3. +244396629458857238594742 = 244396629458857238497869 + 96873. +244396629458857238400996 = 244396629458857238497869 - 96873. +23675434685567877265004063637 = 244396629458857238497869 * 96873. +-244396629458857238497869 = -(244396629458857238497869). +244396629458857238497869 = +(244396629458857238497869). +2522856001763724035 = 244396629458857238497869 div 96873. +55314 = 244396629458857238497869 rem 96873. +2633 = 244396629458857238497869 band 96873. +244396629458857238592109 = 244396629458857238497869 bor 96873. +244396629458857238589476 = 244396629458857238497869 bxor 96873. +-244396629458857238497870 = bnot(244396629458857238497869). +0 = 244396629458857238497869 bsl -748. +361852826053798945056603619852469940983689527163516744953429110981220955101854721603121186998792297986447974170815227941556273391909578309489775202609859011419169533779429522341079176324810902171648165179355508332095987761507345817482628118624600064 = 244396629458857238497869 bsr -748. +9425386805 = -884964 + 9426271769. +-9427156733 = -884964 - 9426271769. +-8341911169781316 = -884964 * 9426271769. +884964 = -(-884964). +-884964 = +(-884964). +0 = -884964 div 9426271769. +-884964 = -884964 rem 9426271769. +9425681944 = -884964 band 9426271769. +-295139 = -884964 bor 9426271769. +-9425977083 = -884964 bxor 9426271769. +884963 = bnot(-884964). +-1 = -884964 bsl -32. +-3800891438137344 = -884964 bsr -32. +-52275425127615427747385716 = -52275425127615134534422791 + -293212962925. +-52275425127614841321459866 = -52275425127615134534422791 - -293212962925. +15327832289832029835910596953758023675 = -52275425127615134534422791 * -293212962925. +52275425127615134534422791 = -(-52275425127615134534422791). +-52275425127615134534422791 = +(-52275425127615134534422791). +178284836407408 = -52275425127615134534422791 div -293212962925. +-122435074391 = -52275425127615134534422791 rem -293212962925. +-52275425127615135676879215 = -52275425127615134534422791 band -293212962925. +-292070506501 = -52275425127615134534422791 bor -293212962925. +52275425127614843606372714 = -52275425127615134534422791 bxor -293212962925. +52275425127615134534422790 = bnot(-52275425127615134534422791). +-102100439702373309637545 = -52275425127615134534422791 bsl -9. +-26765017665338948881624468992 = -52275425127615134534422791 bsr -9. +-5791622013186222891 = 21325272293193394 + -5812947285479416285. +5834272557772609679 = 21325272293193394 - -5812947285479416285. +-123962683688827946451651497738021290 = 21325272293193394 * -5812947285479416285. +-21325272293193394 = -(21325272293193394). +21325272293193394 = +(21325272293193394). +0 = 21325272293193394 div -5812947285479416285. +21325272293193394 = 21325272293193394 rem -5812947285479416285. +18088310044104226 = 21325272293193394 band -5812947285479416285. +-5809710323230327117 = 21325272293193394 bor -5812947285479416285. +-5827798633274431343 = 21325272293193394 bxor -5812947285479416285. +-21325272293193395 = bnot(21325272293193394). +0 = 21325272293193394 bsl -72. +100705751115445181549959465091385524224 = 21325272293193394 bsr -72. +-817650 = -817625 + -25. +-817600 = -817625 - -25. +20440625 = -817625 * -25. +817625 = -(-817625). +-817625 = +(-817625). +32705 = -817625 div -25. +0 = -817625 rem -25. +-817625 = -817625 band -25. +-25 = -817625 bor -25. +817600 = -817625 bxor -25. +817624 = bnot(-817625). +-494223986631205589484568576000 = -817625 bsl 79. +-1 = -817625 bsr 79. +-61546673668249674831 = -61546673668249682778 + 7947. +-61546673668249690725 = -61546673668249682778 - 7947. +-489111415641580229036766 = -61546673668249682778 * 7947. +61546673668249682778 = -(-61546673668249682778). +-61546673668249682778 = +(-61546673668249682778). +-7744642464860913 = -61546673668249682778 div 7947. +-7167 = -61546673668249682778 rem 7947. +7170 = -61546673668249682778 band 7947. +-61546673668249682001 = -61546673668249682778 bor 7947. +-61546673668249689171 = -61546673668249682778 bxor 7947. +61546673668249682777 = bnot(-61546673668249682778). +-12296527315240313535790507724854437742769532445677260456347466338808971349679816879668566025398914953954251685556928523433067603371295396887270529671962667521138491392 = -61546673668249682778 bsl 486. +-1 = -61546673668249682778 bsr 486. +-27965925300435250777907714 = -27965925294615931585626426 + -5819319192281288. +-27965925288796612393345138 = -27965925294615931585626426 - -5819319192281288. +162742645796863224139466778328025478116688 = -27965925294615931585626426 * -5819319192281288. +27965925294615931585626426 = -(-27965925294615931585626426). +-27965925294615931585626426 = +(-27965925294615931585626426). +4805703961 = -27965925294615931585626426 div -5819319192281288. +-1946425217844658 = -27965925294615931585626426 rem -5819319192281288. +-27965925294756682026148352 = -27965925294615931585626426 band -5819319192281288. +-5678568751759362 = -27965925294615931585626426 bor -5819319192281288. +27965925289078113274388990 = -27965925294615931585626426 bxor -5819319192281288. +27965925294615931585626425 = bnot(-27965925294615931585626426). +-15374430021472587653227382187950604288 = -27965925294615931585626426 bsl 39. +-50869721771262 = -27965925294615931585626426 bsr 39. +-331224228819562 = 2873623 + -331224231693185. +331224234566808 = 2873623 - -331224231693185. +-951813570350865359255 = 2873623 * -331224231693185. +-2873623 = -(2873623). +2873623 = +(2873623). +0 = 2873623 div -331224231693185. +2873623 = 2873623 rem -331224231693185. +4119 = 2873623 band -331224231693185. +-331224228823681 = 2873623 bor -331224231693185. +-331224228827800 = 2873623 bxor -331224231693185. +-2873624 = bnot(2873623). +0 = 2873623 bsl -34. +49368467224133632 = 2873623 bsr -34. +-8565982141776 = -8565982141871 + 95. +-8565982141966 = -8565982141871 - 95. +-813768303477745 = -8565982141871 * 95. +8565982141871 = -(-8565982141871). +-8565982141871 = +(-8565982141871). +-90168233072 = -8565982141871 div 95. +-31 = -8565982141871 rem 95. +81 = -8565982141871 band 95. +-8565982141857 = -8565982141871 bor 95. +-8565982141938 = -8565982141871 bxor 95. +8565982141870 = bnot(-8565982141871). +-1 = -8565982141871 bsl -877. +-8631442106926386804633469430411434898438751867311358071196192924586562956798386296912193704448921210697577795369113498160118240574191024547489063711324965470124352836122308377305392149641151166260838018968859937647572032501383839126081894291756559516775212532659331407556902912 = -8565982141871 bsr -877. +-672377636817477109183605829215 = -2381459636356532 + -672377636817474727723969472683. +672377636817472346264333116151 = -2381459636356532 - -672377636817474727723969472683. +1601240202469607707134531348515651407422615356 = -2381459636356532 * -672377636817474727723969472683. +2381459636356532 = -(-2381459636356532). +-2381459636356532 = +(-2381459636356532). +0 = -2381459636356532 div -672377636817474727723969472683. +-2381459636356532 = -2381459636356532 rem -672377636817474727723969472683. +-672377636817477033279646264764 = -2381459636356532 band -672377636817474727723969472683. +-75903959564451 = -2381459636356532 bor -672377636817474727723969472683. +672377636817476957375686700313 = -2381459636356532 bxor -672377636817474727723969472683. +2381459636356531 = bnot(-2381459636356532). +-1 = -2381459636356532 bsl -793. +-124059431457391911820834127222744003825780855300797096084676852440688587721933431499226186664140076792406508037832096528642693463799600994501404016585580340103134786630206913198714638849726646741120678936315390537699641011434629481596256055697334645817344 = -2381459636356532 bsr -793. +243423426533490497385 = -2752962661628964252 + 246176389195119461637. +-248929351856748425889 = -2752962661628964252 - 246176389195119461637. +-677714407628803869811252130296158400524 = -2752962661628964252 * 246176389195119461637. +2752962661628964252 = -(-2752962661628964252). +-2752962661628964252 = +(-2752962661628964252). +0 = -2752962661628964252 div 246176389195119461637. +-2752962661628964252 = -2752962661628964252 rem 246176389195119461637. +246167319718196674564 = -2752962661628964252 band 246176389195119461637. +-2743893184706177179 = -2752962661628964252 bor 246176389195119461637. +-248911212902902851743 = -2752962661628964252 bxor 246176389195119461637. +2752962661628964251 = bnot(-2752962661628964252). +-1 = -2752962661628964252 bsl -344. +-98654938348724579057088257125813202232942319359331674402848732439372762784482382719112423178289753421639095077566867832832 = -2752962661628964252 bsr -344. +59563200878650243717310553 = 387926856318447916625 + 59562812951793925269393928. +-59562425024937606821477303 = 387926856318447916625 - 59562812951793925269393928. +23106014781873150682478281572899806248025253000 = 387926856318447916625 * 59562812951793925269393928. +-387926856318447916625 = -(387926856318447916625). +387926856318447916625 = +(387926856318447916625). +0 = 387926856318447916625 div 59562812951793925269393928. +387926856318447916625 = 387926856318447916625 rem 59562812951793925269393928. +504697853253652992 = 387926856318447916625 band 59562812951793925269393928. +59563200373952390463657561 = 387926856318447916625 bor 59562812951793925269393928. +59563199869254537210004569 = 387926856318447916625 bxor 59562812951793925269393928. +-387926856318447916626 = bnot(387926856318447916625). +0 = 387926856318447916625 bsl -339. +434428568394404113651715053735778402879314662187017182623400694761038553681201573026512080787373278668453710770196185088000 = 387926856318447916625 bsr -339. +-398144453763324514738573635323 = -398144453763324514738573635261 + -62. +-398144453763324514738573635199 = -398144453763324514738573635261 - -62. +24684956133326119913791565386182 = -398144453763324514738573635261 * -62. +398144453763324514738573635261 = -(-398144453763324514738573635261). +-398144453763324514738573635261 = +(-398144453763324514738573635261). +6421684738118137334493123149 = -398144453763324514738573635261 div -62. +-23 = -398144453763324514738573635261 rem -62. +-398144453763324514738573635262 = -398144453763324514738573635261 band -62. +-61 = -398144453763324514738573635261 bor -62. +398144453763324514738573635201 = -398144453763324514738573635261 bxor -62. +398144453763324514738573635260 = bnot(-398144453763324514738573635261). +-66658626423574540504601335910866168511615294895439043499808639641139326582462538933358943305828698678104818612542582390243992313525876300514024008852709600577683640004396953447056036298558556275689987750562606287020911012956502425536525446485803440775585979670704756615591316235396069700234868591477005062590091593068392872935424 = -398144453763324514738573635261 bsl 994. +-1 = -398144453763324514738573635261 bsr 994. +-9214385556315649651785 = -23732441 + -9214385556315625919344. +9214385556315602186903 = -23732441 - -9214385556315625919344. +218679861566512769508902238704 = -23732441 * -9214385556315625919344. +23732441 = -(-23732441). +-23732441 = +(-23732441). +0 = -23732441 div -9214385556315625919344. +-23732441 = -23732441 rem -9214385556315625919344. +-9214385556315632743424 = -23732441 band -9214385556315625919344. +-16908361 = -23732441 bor -9214385556315625919344. +9214385556315615835063 = -23732441 bxor -9214385556315625919344. +23732440 = bnot(-23732441). +-189859528 = -23732441 bsl 3. +-2966556 = -23732441 bsr 3. +-5372494371976352850019706251 = -5372494272395186453391223932 + -99581166396628482319. +-5372494172814020056762741613 = -5372494272395186453391223932 - -99581166396628482319. +534999246104318529343725713325254090903031658308 = -5372494272395186453391223932 * -99581166396628482319. +5372494272395186453391223932 = -(-5372494272395186453391223932). +-5372494272395186453391223932 = +(-5372494272395186453391223932). +53950907 = -5372494272395186453391223932 div -99581166396628482319. +-25179158090247710599 = -5372494272395186453391223932 rem -99581166396628482319. +-5372494371618570459932474752 = -5372494272395186453391223932 band -99581166396628482319. +-357782390087231499 = -5372494272395186453391223932 bor -99581166396628482319. +5372494371260788069845243253 = -5372494272395186453391223932 bxor -99581166396628482319. +5372494272395186453391223931 = bnot(-5372494272395186453391223932). +-1 = -5372494272395186453391223932 bsl -854. +-645345458602619608664758166580222950342667274088042452990234746151398093692985776277122254975220509919775283657920615386043642023172791487611710501770303088256267014951620113959939334848651815055530778938513276209771519928127843414309468085959460683078343358732552273870214550507225088 = -5372494272395186453391223932 bsr -854. +-622311400235520025 = -622311491388362663 + 91152842638. +-622311582541205301 = -622311491388362663 - 91152842638. +-56725461446342513964913624994 = -622311491388362663 * 91152842638. +622311491388362663 = -(-622311491388362663). +-622311491388362663 = +(-622311491388362663). +-6827121 = -622311491388362663 div 91152842638. +-5204777465 = -622311491388362663 rem 91152842638. +86572609544 = -622311491388362663 band 91152842638. +-622311486808129569 = -622311491388362663 bor 91152842638. +-622311573380739113 = -622311491388362663 bxor 91152842638. +622311491388362662 = bnot(-622311491388362663). +-175165112545312982471309344636928 = -622311491388362663 bsl 48. +-2211 = -622311491388362663 bsr 48. +-45751395297 = -45751395299 + 2. +-45751395301 = -45751395299 - 2. +-91502790598 = -45751395299 * 2. +45751395299 = -(-45751395299). +-45751395299 = +(-45751395299). +-22875697649 = -45751395299 div 2. +-1 = -45751395299 rem 2. +0 = -45751395299 band 2. +-45751395297 = -45751395299 bor 2. +-45751395297 = -45751395299 bxor 2. +45751395298 = bnot(-45751395299). +-210991070023942822323915063296 = -45751395299 bsl 62. +-1 = -45751395299 bsr 62. +649148398141948497246 = 83997982 + 649148398141864499264. +-649148398141780501282 = 83997982 - 649148398141864499264. +54527155462449167655616485248 = 83997982 * 649148398141864499264. +-83997982 = -(83997982). +83997982 = +(83997982). +0 = 83997982 div 649148398141864499264. +83997982 = 83997982 rem 649148398141864499264. +83955712 = 83997982 band 649148398141864499264. +649148398141864541534 = 83997982 bor 649148398141864499264. +649148398141780585822 = 83997982 bxor 649148398141864499264. +-83997983 = bnot(83997982). +0 = 83997982 bsl -58. +24210769947844712341700608 = 83997982 bsr -58. +-53736505071733726558540 = -53727351395785129141971 + -9153675948597416569. +-53718197719836531725402 = -53727351395785129141971 - -9153675948597416569. +491802764253440175135261132926726228717499 = -53727351395785129141971 * -9153675948597416569. +53727351395785129141971 = -(-53727351395785129141971). +-53727351395785129141971 = +(-53727351395785129141971). +5869 = -53727351395785129141971 div -9153675948597416569. +-4427253466891298510 = -53727351395785129141971 rem -9153675948597416569. +-53735349860211478214395 = -53727351395785129141971 band -9153675948597416569. +-1155211522248344145 = -53727351395785129141971 bor -9153675948597416569. +53734194648689229870250 = -53727351395785129141971 bxor -9153675948597416569. +53727351395785129141970 = bnot(-53727351395785129141971). +-3127343451825 = -53727351395785129141971 bsl -34. +-923028868582388327631607943921664 = -53727351395785129141971 bsr -34. +96451138707169 = 96451212451614 + -73744445. +96451286196059 = 96451212451614 - -73744445. +-7112741131821363784230 = 96451212451614 * -73744445. +-96451212451614 = -(96451212451614). +96451212451614 = +(96451212451614). +-1307911 = 96451212451614 div -73744445. +41647219 = 96451212451614 rem -73744445. +96451141082882 = 96451212451614 band -73744445. +-2375713 = 96451212451614 bor -73744445. +-96451143458595 = 96451212451614 bxor -73744445. +-96451212451615 = bnot(96451212451614). +49383020775226368 = 96451212451614 bsl 9. +188381274319 = 96451212451614 bsr 9. +-57601894722972806209645 = -57667814637436523686832 + 65919914463717477187. +-57733734551900241164019 = -57667814637436523686832 - 65919914463717477187. +-3801457408209330340454544221357103092301584 = -57667814637436523686832 * 65919914463717477187. +57667814637436523686832 = -(-57667814637436523686832). +-57667814637436523686832 = +(-57667814637436523686832). +-874 = -57667814637436523686832 div 65919914463717477187. +-53809396147448625394 = -57667814637436523686832 rem 65919914463717477187. +28985752554527866944 = -57667814637436523686832 band 65919914463717477187. +-57630880475527334076589 = -57667814637436523686832 bor 65919914463717477187. +-57659866228081861943533 = -57667814637436523686832 bxor 65919914463717477187. +57667814637436523686831 = bnot(-57667814637436523686832). +-461342517099492189494656 = -57667814637436523686832 bsl 3. +-7208476829679565460854 = -57667814637436523686832 bsr 3. +5495366208771220 = 5495368997358978 + -2788587758. +5495371785946736 = 5495368997358978 - -2788587758. +-15324318711727980382191324 = 5495368997358978 * -2788587758. +-5495368997358978 = -(5495368997358978). +5495368997358978 = +(5495368997358978). +-1970663 = 5495368997358978 div -2788587758. +2280415424 = 5495368997358978 rem -2788587758. +5495368926692610 = 5495368997358978 band -2788587758. +-2717921390 = 5495368997358978 bor -2788587758. +-5495371644614000 = 5495368997358978 bxor -2788587758. +-5495368997358979 = bnot(5495368997358978). +0 = 5495368997358978 bsl -453. +127815903730368892198224471153194858502094152297957879933628492677771799528319523153257752893153933771965334340879654516057785486043490331701019647410176 = 5495368997358978 bsr -453. +-82828718716766876699 = -5674763721141391318 + -77153954995625485381. +71479191274484094063 = -5674763721141391318 - -77153954995625485381. +437830464751751117528858834313409322158 = -5674763721141391318 * -77153954995625485381. +5674763721141391318 = -(-5674763721141391318). +-5674763721141391318 = +(-5674763721141391318). +0 = -5674763721141391318 div -77153954995625485381. +-5674763721141391318 = -5674763721141391318 rem -77153954995625485381. +-81783662566975434710 = -5674763721141391318 band -77153954995625485381. +-1045056149791441989 = -5674763721141391318 bor -77153954995625485381. +80738606417183992721 = -5674763721141391318 bxor -77153954995625485381. +5674763721141391317 = bnot(-5674763721141391318). +-1452739512612196177408 = -5674763721141391318 bsl 8. +-22167045785708560 = -5674763721141391318 bsr 8. +62049501291561 = 7638117936322 + 54411383355239. +-46773265418917 = 7638117936322 - 54411383355239. +415600563145743330907090958 = 7638117936322 * 54411383355239. +-7638117936322 = -(7638117936322). +7638117936322 = +(7638117936322). +0 = 7638117936322 div 54411383355239. +7638117936322 = 7638117936322 rem 54411383355239. +481624335426 = 7638117936322 band 54411383355239. +61567876956135 = 7638117936322 bor 54411383355239. +61086252620709 = 7638117936322 bxor 54411383355239. +-7638117936323 = bnot(7638117936322). +30552471745288 = 7638117936322 bsl 2. +1909529484080 = 7638117936322 bsr 2. +718248518674927168763 = -79 + 718248518674927168842. +-718248518674927168921 = -79 - 718248518674927168842. +-56741632975319246338518 = -79 * 718248518674927168842. +79 = -(-79). +-79 = +(-79). +0 = -79 div 718248518674927168842. +-79 = -79 rem 718248518674927168842. +718248518674927168768 = -79 band 718248518674927168842. +-5 = -79 bor 718248518674927168842. +-718248518674927168773 = -79 bxor 718248518674927168842. +78 = bnot(-79). +-1 = -79 bsl -598. +-81952932485399610930620055307900432732495813086788128774914232261390393025404935891394214216705299937191908260573190586352304233739382562330765777973750782819458340617179813092786176 = -79 bsr -598. +-576591030072400 = 728492118 + -576591758564518. +576592487056636 = 728492118 - -576591758564518. +-420042551418010357469124 = 728492118 * -576591758564518. +-728492118 = -(728492118). +728492118 = +(728492118). +0 = 728492118 div -576591758564518. +728492118 = 728492118 rem -576591758564518. +17358930 = 728492118 band -576591758564518. +-576591047431330 = 728492118 bor -576591758564518. +-576591064790260 = 728492118 bxor -576591758564518. +-728492119 = bnot(728492118). +0 = 728492118 bsl -526. +160030431586239744892753319833238291175662243150891592358740153051381853076922268596681019782617022390917057017573357357693450229193093160027956764850762514123248893952 = 728492118 bsr -526. +-924392572229326523195129 = 612 + -924392572229326523195741. +924392572229326523196353 = 612 - -924392572229326523195741. +-565728254204347832195793492 = 612 * -924392572229326523195741. +-612 = -(612). +612 = +(612). +0 = 612 div -924392572229326523195741. +612 = 612 rem -924392572229326523195741. +544 = 612 band -924392572229326523195741. +-924392572229326523195673 = 612 bor -924392572229326523195741. +-924392572229326523196217 = 612 bxor -924392572229326523195741. +-613 = bnot(612). +1 = 612 bsl -9. +313344 = 612 bsr -9. +-85364771073575410040667221 = -85887184662464988616143357 + 522413588889578575476136. +-86409598251354567191619493 = -85887184662464988616143357 - 522413588889578575476136. +-44868632379140303011030046969722375335512308428552 = -85887184662464988616143357 * 522413588889578575476136. +85887184662464988616143357 = -(-85887184662464988616143357). +-85887184662464988616143357 = +(-85887184662464988616143357). +-164 = -85887184662464988616143357 div 522413588889578575476136. +-211356084574102238057053 = -85887184662464988616143357 rem 522413588889578575476136. +475188183418524194472960 = -85887184662464988616143357 band 522413588889578575476136. +-85839959256993934235140181 = -85887184662464988616143357 bor 522413588889578575476136. +-86315147440412458429613141 = -85887184662464988616143357 bxor 522413588889578575476136. +85887184662464988616143356 = bnot(-85887184662464988616143357). +-3168677829359847849991594780148158367294029824 = -85887184662464988616143357 bsl 65. +-2327977 = -85887184662464988616143357 bsr 65. +-98899404120945813 = 484548812438515 + -99383952933384328. +99868501745822843 = 484548812438515 - -99383952933384328. +-48156376369316645392401364592920 = 484548812438515 * -99383952933384328. +-484548812438515 = -(484548812438515). +484548812438515 = +(484548812438515). +0 = 484548812438515 div -99383952933384328. +484548812438515 = 484548812438515 rem -99383952933384328. +185337586387824 = 484548812438515 band -99383952933384328. +-99084741707333637 = 484548812438515 bor -99383952933384328. +-99270079293721461 = 484548812438515 bxor -99383952933384328. +-484548812438516 = bnot(484548812438515). +30679974992315889390798967663773782424471480578356502615503704551121426715147114584348015495816231245911833067790307608342690846808918881379420686041269395371370242315457964130051387807498240 = 484548812438515 bsl 584. +0 = 484548812438515 bsr 584. +968455268434 = -997599999 + 969452868433. +-970450468432 = -997599999 - 969452868433. +-967126180579307931567 = -997599999 * 969452868433. +997599999 = -(-997599999). +-997599999 = +(-997599999). +0 = -997599999 div 969452868433. +-997599999 = -997599999 rem 969452868433. +968590676225 = -997599999 band 969452868433. +-135407791 = -997599999 bor 969452868433. +-968726084016 = -997599999 bxor 969452868433. +997599998 = bnot(-997599999). +-1 = -997599999 bsl -797. +-831501398946616023867775734042959373463794138149698957311924829077443217085354064591518586508503794946699073508134886259423178510532584618756389864680235000206712394403502918001094042445318423144725184421024432250131011032561971218323577847391715328 = -997599999 bsr -797. +-39877824187112479 = 51357 + -39877824187163836. +39877824187215193 = 51357 - -39877824187163836. +-2048005416780173125452 = 51357 * -39877824187163836. +-51357 = -(51357). +51357 = +(51357). +0 = 51357 div -39877824187163836. +51357 = 51357 rem -39877824187163836. +34820 = 51357 band -39877824187163836. +-39877824187147299 = 51357 bor -39877824187163836. +-39877824187182119 = 51357 bxor -39877824187163836. +-51358 = bnot(51357). +121263287730368184619892736 = 51357 bsl 71. +0 = 51357 bsr 71. +78387 = -7 + 78394. +-78401 = -7 - 78394. +-548758 = -7 * 78394. +7 = -(-7). +-7 = +(-7). +0 = -7 div 78394. +-7 = -7 rem 78394. +78392 = -7 band 78394. +-5 = -7 bor 78394. +-78397 = -7 bxor 78394. +6 = bnot(-7). +-1 = -7 bsl -35. +-240518168576 = -7 bsr -35. +9665926958347581 = 98633 + 9665926958248948. +-9665926958150315 = 98633 - 9665926958248948. +953379373672968488084 = 98633 * 9665926958248948. +-98633 = -(98633). +98633 = +(98633). +0 = 98633 div 9665926958248948. +98633 = 98633 rem 9665926958248948. +65856 = 98633 band 9665926958248948. +9665926958281725 = 98633 bor 9665926958248948. +9665926958215869 = 98633 bxor 9665926958248948. +-98634 = bnot(98633). +0 = 98633 bsl -242. +697077706161145526319157529563105127886448876802131698785633537808379865464832 = 98633 bsr -242. +999444115635065983079250079840 = 999444115631184126856775915218 + 3881856222474164622. +999444115627302270634301750596 = 999444115631184126856775915218 - 3881856222474164622. +3879698359278100601364997602272180986374047017596 = 999444115631184126856775915218 * 3881856222474164622. +-999444115631184126856775915218 = -(999444115631184126856775915218). +999444115631184126856775915218 = +(999444115631184126856775915218). +257465516070 = 999444115631184126856775915218 div 3881856222474164622. +2332600211409439678 = 999444115631184126856775915218 rem 3881856222474164622. +25056404357271682 = 999444115631184126856775915218 band 3881856222474164622. +999444115635040926674892808158 = 999444115631184126856775915218 bor 3881856222474164622. +999444115635015870270535536476 = 999444115631184126856775915218 bxor 3881856222474164622. +-999444115631184126856775915219 = bnot(999444115631184126856775915218). +249861028907796031714193978804 = 999444115631184126856775915218 bsl -2. +3997776462524736507427103660872 = 999444115631184126856775915218 bsr -2. +-7421760831679509280811286683 = -7422292158463252213136449141 + 531326783742932325162458. +-7422823485246995145461611599 = -7422292158463252213136449141 - 531326783742932325162458. +-3943662620556666793445602995377124133609104079548578 = -7422292158463252213136449141 * 531326783742932325162458. +7422292158463252213136449141 = -(-7422292158463252213136449141). +-7422292158463252213136449141 = +(-7422292158463252213136449141). +-13969 = -7422292158463252213136449141 div 531326783742932325162458. +-188316358230562942073339 = -7422292158463252213136449141 rem 531326783742932325162458. +453407718756634929824138 = -7422292158463252213136449141 band 531326783742932325162458. +-7422214239398265915741110821 = -7422292158463252213136449141 bor 531326783742932325162458. +-7422667647117022550670934959 = -7422292158463252213136449141 bxor 531326783742932325162458. +7422292158463252213136449140 = bnot(-7422292158463252213136449141). +-1728137060642068324 = -7422292158463252213136449141 bsl -32. +-31878502081956917873220670646162292736 = -7422292158463252213136449141 bsr -32. +-887410717883738347 = -887411542626632718 + 824742894371. +-887412367369527089 = -887411542626632718 - 824742894371. +-731886364164123111632886630378 = -887411542626632718 * 824742894371. +887411542626632718 = -(-887411542626632718). +-887411542626632718 = +(-887411542626632718). +-1075985 = -887411542626632718 div 824742894371. +-559426852283 = -887411542626632718 rem 824742894371. +824633744162 = -887411542626632718 band 824742894371. +-887411542517482509 = -887411542626632718 bor 824742894371. +-887412367151226671 = -887411542626632718 bxor 824742894371. +887411542626632717 = bnot(-887411542626632718). +-1 = -887411542626632718 bsl -329. +-970495769895456546915019153080417053119984920561167837968648469580707157753110011803004098876328273565803987196706816 = -887411542626632718 bsr -329. +313568626669534262696946623 = 313568626669533918717171286 + 343979775337. +313568626669533574737395949 = 313568626669533918717171286 - 343979775337. +107861265754517903902833798202427373382 = 313568626669533918717171286 * 343979775337. +-313568626669533918717171286 = -(313568626669533918717171286). +313568626669533918717171286 = +(313568626669533918717171286). +911590300221366 = 313568626669533918717171286 div 343979775337. +60669920944 = 313568626669533918717171286 rem 343979775337. +275222516800 = 313568626669533918717171286 band 343979775337. +313568626669533987474429823 = 313568626669533918717171286 bor 343979775337. +313568626669533712251913023 = 313568626669533918717171286 bxor 343979775337. +-313568626669533918717171287 = bnot(313568626669533918717171286). +78392156667383479679292821 = 313568626669533918717171286 bsl -2. +1254274506678135674868685144 = 313568626669533918717171286 bsr -2. +1030797516921412947901481 = 948853774157265434517939 + 81943742764147513383542. +866910031393117921134397 = 948853774157265434517939 - 81943742764147513383542. +77752629590333478278519214703311340021586359938 = 948853774157265434517939 * 81943742764147513383542. +-948853774157265434517939 = -(948853774157265434517939). +948853774157265434517939 = +(948853774157265434517939). +11 = 948853774157265434517939 div 81943742764147513383542. +47472603751642787298977 = 948853774157265434517939 rem 81943742764147513383542. +1330856053278681202738 = 948853774157265434517939 band 81943742764147513383542. +1029466660868134266698743 = 948853774157265434517939 bor 81943742764147513383542. +1028135804814855585496005 = 948853774157265434517939 bxor 81943742764147513383542. +-948853774157265434517940 = bnot(948853774157265434517939). +0 = 948853774157265434517939 bsl -753. +44955830423796552989937230141548278995130022619090864557796782625730192137398224697416208564819328265689801653760488324197488078265293703127019736304678811815553524422839974370260849677832477301506583027387430880948825277017160289147874622970934591488 = 948853774157265434517939 bsr -753. +-69127735311 = 64125 + -69127799436. +69127863561 = 64125 - -69127799436. +-4432820138833500 = 64125 * -69127799436. +-64125 = -(64125). +64125 = +(64125). +0 = 64125 div -69127799436. +64125 = 64125 rem -69127799436. +30836 = 64125 band -69127799436. +-69127766147 = 64125 bor -69127799436. +-69127796983 = 64125 bxor -69127799436. +-64126 = bnot(64125). +2052000 = 64125 bsl 5. +2003 = 64125 bsr 5. +-5279768325556361346253573 = -4432399871885 + -5279768325551928946381688. +5279768325547496546509803 = -4432399871885 - -5279768325551928946381688. +23402044449758850833856816925510041880 = -4432399871885 * -5279768325551928946381688. +4432399871885 = -(-4432399871885). +-4432399871885 = +(-4432399871885). +0 = -4432399871885 div -5279768325551928946381688. +-4432399871885 = -4432399871885 rem -5279768325551928946381688. +-5279768325551958567878656 = -4432399871885 band -5279768325551928946381688. +-4402778374917 = -4432399871885 bor -5279768325551928946381688. +5279768325547555789503739 = -4432399871885 bxor -5279768325551928946381688. +4432399871884 = bnot(-4432399871885). +-283673591800640 = -4432399871885 bsl 6. +-69256247999 = -4432399871885 bsr 6. +-682115273248931533421569716 = 2121756217159 + -682115273248933655177786875. +682115273248935776934004034 = 2121756217159 - -682115273248933655177786875. +-1447282321835035099940583993505519988125 = 2121756217159 * -682115273248933655177786875. +-2121756217159 = -(2121756217159). +2121756217159 = +(2121756217159). +0 = 2121756217159 div -682115273248933655177786875. +2121756217159 = 2121756217159 rem -682115273248933655177786875. +1786714786309 = 2121756217159 band -682115273248933655177786875. +-682115273248933320136356025 = 2121756217159 bor -682115273248933655177786875. +-682115273248935106851142334 = 2121756217159 bxor -682115273248933655177786875. +-2121756217160 = bnot(2121756217159). +271584795796352 = 2121756217159 bsl 7. +16576220446 = 2121756217159 bsr 7. +-2701221790617 = -2644899318861 + -56322471756. +-2588576847105 = -2644899318861 - -56322471756. +148967267184012310589916 = -2644899318861 * -56322471756. +2644899318861 = -(-2644899318861). +-2644899318861 = +(-2644899318861). +46 = -2644899318861 div -56322471756. +-54065618085 = -2644899318861 rem -56322471756. +-2679478484816 = -2644899318861 band -56322471756. +-21743305801 = -2644899318861 bor -56322471756. +2657735179015 = -2644899318861 bxor -56322471756. +2644899318860 = bnot(-2644899318861). +-15018869115712881537722849356305578217847074295132537190932634107335313073669235165106989168393649706480152428938986012858339815450764726105014272 = -2644899318861 bsl 441. +-1 = -2644899318861 bsr 441. +815052126 = 3762931 + 811289195. +-807526264 = 3762931 - 811289195. +3052825261830545 = 3762931 * 811289195. +-3762931 = -(3762931). +3762931 = +(3762931). +0 = 3762931 div 811289195. +3762931 = 3762931 rem 811289195. +1657443 = 3762931 band 811289195. +813394683 = 3762931 bor 811289195. +811737240 = 3762931 bxor 811289195. +-3762932 = bnot(3762931). +1137276110832074043751571390464 = 3762931 bsl 78. +0 = 3762931 bsr 78. +49521116610 = -5716127151 + 55237243761. +-60953370912 = -5716127151 - 55237243761. +-315743108808657454911 = -5716127151 * 55237243761. +5716127151 = -(-5716127151). +-5716127151 = +(-5716127151). +0 = -5716127151 div 55237243761. +-5716127151 = -5716127151 rem 55237243761. +53825524305 = -5716127151 band 55237243761. +-4304407695 = -5716127151 bor 55237243761. +-58129932000 = -5716127151 bxor 55237243761. +5716127150 = bnot(-5716127151). +-1 = -5716127151 bsl -296. +-727747290743084335959424417130358281838296824590763414131023965275244960523992426285614207898484736 = -5716127151 bsr -296. +6544231478191377 = -486656422 + 6544231964847799. +-6544232451504221 = -486656422 - 6544231964847799. +-3184792512750859635915178 = -486656422 * 6544231964847799. +486656422 = -(-486656422). +-486656422 = +(-486656422). +0 = -486656422 div 6544231964847799. +-486656422 = -486656422 rem 6544231964847799. +6544231478208018 = -486656422 band 6544231964847799. +-16641 = -486656422 bor 6544231964847799. +-6544231478224659 = -486656422 bxor 6544231964847799. +486656421 = bnot(-486656422). +-301225735084581300745892102892683264 = -486656422 bsl 89. +-1 = -486656422 bsr 89. +778717791186742215227726143792 = 961172988421 + 778717791186742214266553155371. +-778717791186742213305380166950 = 961172988421 - 778717791186742214266553155371. +748482506491561270161937597014991196959191 = 961172988421 * 778717791186742214266553155371. +-961172988421 = -(961172988421). +961172988421 = +(961172988421). +0 = 961172988421 div 778717791186742214266553155371. +961172988421 = 961172988421 rem 778717791186742214266553155371. +552977605121 = 961172988421 band 778717791186742214266553155371. +778717791186742214674748538671 = 961172988421 bor 778717791186742214266553155371. +778717791186742214121770933550 = 961172988421 bxor 778717791186742214266553155371. +-961172988422 = bnot(961172988421). +1877290993 = 961172988421 bsl -9. +492120570071552 = 961172988421 bsr -9. +248781815992745712161 = 217 + 248781815992745711944. +-248781815992745711727 = 217 - 248781815992745711944. +53985654070425819491848 = 217 * 248781815992745711944. +-217 = -(217). +217 = +(217). +0 = 217 div 248781815992745711944. +217 = 217 rem 248781815992745711944. +72 = 217 band 248781815992745711944. +248781815992745712089 = 217 bor 248781815992745711944. +248781815992745712017 = 217 bxor 248781815992745711944. +-218 = bnot(217). +0 = 217 bsl -384. +8550235344617601989064551701731164195702303421691001926944779668721321624414894702676895777310026694055038273896579072 = 217 bsr -384. +-85735918 = 3889577 + -89625495. +93515072 = 3889577 - -89625495. +-348605263965615 = 3889577 * -89625495. +-3889577 = -(3889577). +3889577 = +(3889577). +0 = 3889577 div -89625495. +3889577 = 3889577 rem -89625495. +2639913 = 3889577 band -89625495. +-88375831 = 3889577 bor -89625495. +-91015744 = 3889577 bxor -89625495. +-3889578 = bnot(3889577). +62233232 = 3889577 bsl 4. +243098 = 3889577 bsr 4. +3360943323643976598 = 3883621238878422729 + -522677915234446131. +4406299154112868860 = 3883621238878422729 - -522677915234446131. +-2029883052697190904206803023196511499 = 3883621238878422729 * -522677915234446131. +-3883621238878422729 = -(3883621238878422729). +3883621238878422729 = +(3883621238878422729). +-7 = 3883621238878422729 div -522677915234446131. +224875832237299812 = 3883621238878422729 rem -522677915234446131. +3505208093292250313 = 3883621238878422729 band -522677915234446131. +-144264769648273715 = 3883621238878422729 bor -522677915234446131. +-3649472862940524028 = 3883621238878422729 bxor -522677915234446131. +-3883621238878422730 = bnot(3883621238878422729). +0 = 3883621238878422729 bsl -389. +4896718979799578121787780444971369924407880135835598510635873693211107237295224873386902521754369854131955746958494421577321819456667648 = 3883621238878422729 bsr -389. +498254268939163057825040291 = 895382574868 + 498254268939162162442465423. +-498254268939161267059890555 = 895382574868 - 498254268939162162442465423. +446128190261719971850333574351798789164 = 895382574868 * 498254268939162162442465423. +-895382574868 = -(895382574868). +895382574868 = +(895382574868). +0 = 895382574868 div 498254268939162162442465423. +895382574868 = 895382574868 rem 498254268939162162442465423. +550162976772 = 895382574868 band 498254268939162162442465423. +498254268939162507662063519 = 895382574868 bor 498254268939162162442465423. +498254268939161957499086747 = 895382574868 bxor 498254268939162162442465423. +-895382574869 = bnot(895382574868). +416 = 895382574868 bsl -31. +1922819438233165758464 = 895382574868 bsr -31. +34461789487513 = 34461789487594 + -81. +34461789487675 = 34461789487594 - -81. +-2791404948495114 = 34461789487594 * -81. +-34461789487594 = -(34461789487594). +34461789487594 = +(34461789487594). +-425454191204 = 34461789487594 div -81. +70 = 34461789487594 rem -81. +34461789487530 = 34461789487594 band -81. +-17 = 34461789487594 bor -81. +-34461789487547 = 34461789487594 bxor -81. +-34461789487595 = bnot(34461789487594). +232272001660026703760366764807388926368265233083387462586811750474488235820056576 = 34461789487594 bsl 222. +0 = 34461789487594 bsr 222. +-58613221819218149614641 = -58613221819218149646763 + 32122. +-58613221819218149678885 = -58613221819218149646763 - 32122. +-1882773911276925402953321086 = -58613221819218149646763 * 32122. +58613221819218149646763 = -(-58613221819218149646763). +-58613221819218149646763 = +(-58613221819218149646763). +-1824706488363680644 = -58613221819218149646763 div 32122. +-195 = -58613221819218149646763 rem 32122. +23632 = -58613221819218149646763 band 32122. +-58613221819218149638273 = -58613221819218149646763 bor 32122. +-58613221819218149661905 = -58613221819218149646763 bxor 32122. +58613221819218149646762 = bnot(-58613221819218149646763). +-115353780013824240609754035330166356835530807146082501076917294201730599832145189329658309317264927314622238725685567526053775984409131220351199561714585926564441368296923936159972926723881633284496272440549628177999460373025776789014171764136993061539354648264840701399373720351408128 = -58613221819218149646763 bsl 868. +-1 = -58613221819218149646763 bsr 868. +-648607 = -648663 + 56. +-648719 = -648663 - 56. +-36325128 = -648663 * 56. +648663 = -(-648663). +-648663 = +(-648663). +-11583 = -648663 div 56. +-15 = -648663 rem 56. +40 = -648663 band 56. +-648647 = -648663 bor 56. +-648687 = -648663 bxor 56. +648662 = bnot(-648663). +-5068 = -648663 bsl -7. +-83028864 = -648663 bsr -7. +-211455963197590501059607 = -211455963197594943585752 + 4442526145. +-211455963197599386111897 = -211455963197594943585752 - 4442526145. +-939398645021473337999503309486040 = -211455963197594943585752 * 4442526145. +211455963197594943585752 = -(-211455963197594943585752). +-211455963197594943585752 = +(-211455963197594943585752). +-47598135901931 = -211455963197594943585752 div 4442526145. +-3320099757 = -211455963197594943585752 rem 4442526145. +4299194368 = -211455963197594943585752 band 4442526145. +-211455963197594800253975 = -211455963197594943585752 bor 4442526145. +-211455963197599099448343 = -211455963197594943585752 bxor 4442526145. +211455963197594943585751 = bnot(-211455963197594943585752). +-54132726578584305557952512 = -211455963197594943585752 bsl 8. +-825999856240605248382 = -211455963197594943585752 bsr 8. +-3973112315127790593229 = -3972863948889215724974 + -248366238574868255. +-3972615582650640856719 = -3972863948889215724974 - -248366238574868255. +986725275355312154032587659946363300370 = -3972863948889215724974 * -248366238574868255. +3972863948889215724974 = -(-3972863948889215724974). +-3972863948889215724974 = +(-3972863948889215724974). +15995 = -3972863948889215724974 div -248366238574868255. +-245962884197986249 = -3972863948889215724974 rem -248366238574868255. +-3972963669672093286336 = -3972863948889215724974 band -248366238574868255. +-148645455697306893 = -3972863948889215724974 bor -248366238574868255. +3972815024216395979443 = -3972863948889215724974 bxor -248366238574868255. +3972863948889215724973 = bnot(-3972863948889215724974). +-1 = -3972863948889215724974 bsl -98. +-1259050842358627002143885165651655811471832363565056 = -3972863948889215724974 bsr -98. +-558635317797086 = -558635322194377 + 4397291. +-558635326591668 = -558635322194377 - 4397291. +-2456482074567434232707 = -558635322194377 * 4397291. +558635322194377 = -(-558635322194377). +-558635322194377 = +(-558635322194377). +-127040789 = -558635322194377 div 4397291. +-4091778 = -558635322194377 rem 4397291. +196643 = -558635322194377 band 4397291. +-558635317993729 = -558635322194377 bor 4397291. +-558635318190372 = -558635322194377 bxor 4397291. +558635322194376 = bnot(-558635322194377). +-4469082577555016 = -558635322194377 bsl 3. +-69829415274298 = -558635322194377 bsr 3. +-412756587134358128931489395 = 854997971 + -412756587134358129786487366. +412756587134358130641485337 = 854997971 - -412756587134358129786487366. +-352906044516760905354801361147134386 = 854997971 * -412756587134358129786487366. +-854997971 = -(854997971). +854997971 = +(854997971). +0 = 854997971 div -412756587134358129786487366. +854997971 = 854997971 rem -412756587134358129786487366. +43399570 = 854997971 band -412756587134358129786487366. +-412756587134358128974888965 = 854997971 bor -412756587134358129786487366. +-412756587134358129018288535 = 854997971 bxor -412756587134358129786487366. +-854997972 = bnot(854997971). +0 = 854997971 bsl -867. +841339588559027968657139068853479070517085189036390509696375594633682764255723855003503859399509987968043180973990640978757883815265442996100067617822859505102539561134888814730475971954120773134914827626854172581891142155887893016986662978936934078264133426162945753088 = 854997971 bsr -867. +-97495118883786324533104878919 = -97495118883786564252296322472 + 239719191443553. +-97495118883786803971487766025 = -97495118883786564252296322472 - 239719191443553. +-23371451068514390665490176249061750873423016 = -97495118883786564252296322472 * 239719191443553. +97495118883786564252296322472 = -(-97495118883786564252296322472). +-97495118883786564252296322472 = +(-97495118883786564252296322472). +-406705521976298 = -97495118883786564252296322472 div 239719191443553. +-232128225415678 = -97495118883786564252296322472 rem 239719191443553. +90184246911040 = -97495118883786564252296322472 band 239719191443553. +-97495118883786414717351789959 = -97495118883786564252296322472 bor 239719191443553. +-97495118883786504901598700999 = -97495118883786564252296322472 bxor 239719191443553. +97495118883786564252296322471 = bnot(-97495118883786564252296322472). +-761680616279582533221065020 = -97495118883786564252296322472 bsl -7. +-12479375217124680224293929276416 = -97495118883786564252296322472 bsr -7. +83 = 6 + 77. +-71 = 6 - 77. +462 = 6 * 77. +-6 = -(6). +6 = +(6). +0 = 6 div 77. +6 = 6 rem 77. +4 = 6 band 77. +79 = 6 bor 77. +75 = 6 bxor 77. +-7 = bnot(6). +24 = 6 bsl 2. +1 = 6 bsr 2. +2272412686867798218988 = 222618662789 + 2272412686645179556199. +-2272412686422560893410 = 222618662789 - 2272412686645179556199. +505881473605708751313821855579011 = 222618662789 * 2272412686645179556199. +-222618662789 = -(222618662789). +222618662789 = +(222618662789). +0 = 222618662789 div 2272412686645179556199. +222618662789 = 222618662789 rem 2272412686645179556199. +218239672581 = 222618662789 band 2272412686645179556199. +2272412686649558546407 = 222618662789 bor 2272412686645179556199. +2272412686431318873826 = 222618662789 bxor 2272412686645179556199. +-222618662790 = bnot(222618662789). +61192952074112457506816 = 222618662789 bsl 38. +0 = 222618662789 bsr 38. +-95427743251695916914283324936 = -95427743251695916914283328493 + 3557. +-95427743251695916914283332050 = -95427743251695916914283328493 - 3557. +-339436482746282376464105799449601 = -95427743251695916914283328493 * 3557. +95427743251695916914283328493 = -(-95427743251695916914283328493). +-95427743251695916914283328493 = +(-95427743251695916914283328493). +-26828153852037086565724860 = -95427743251695916914283328493 div 3557. +-1473 = -95427743251695916914283328493 rem 3557. +3073 = -95427743251695916914283328493 band 3557. +-95427743251695916914283328009 = -95427743251695916914283328493 bor 3557. +-95427743251695916914283331082 = -95427743251695916914283328493 bxor 3557. +95427743251695916914283328492 = bnot(-95427743251695916914283328493). +-3053687784054269341257066511776 = -95427743251695916914283328493 bsl 5. +-2982116976615497403571354016 = -95427743251695916914283328493 bsr 5. +538947190970 = 63698 + 538947127272. +-538947063574 = 63698 - 538947127272. +34329854112971856 = 63698 * 538947127272. +-63698 = -(63698). +63698 = +(63698). +0 = 63698 div 538947127272. +63698 = 63698 rem 538947127272. +32960 = 63698 band 538947127272. +538947158010 = 63698 bor 538947127272. +538947125050 = 63698 bxor 538947127272. +-63699 = bnot(63698). +36719397000223469338624 = 63698 bsl 59. +0 = 63698 bsr 59. +-2814956792591 = -2814594177148 + -362615443. +-2814231561705 = -2814594177148 - -362615443. +1020615314411742496564 = -2814594177148 * -362615443. +2814594177148 = -(-2814594177148). +-2814594177148 = +(-2814594177148). +7761 = -2814594177148 div -362615443. +-335724025 = -2814594177148 rem -362615443. +-2814679964412 = -2814594177148 band -362615443. +-276828179 = -2814594177148 bor -362615443. +2814403136233 = -2814594177148 bxor -362615443. +2814594177147 = bnot(-2814594177148). +-90067013668736 = -2814594177148 bsl 5. +-87956068036 = -2814594177148 bsr 5. +-74795892476115149750695 = -74795892476178575122683 + 63425371988. +-74795892476242000494671 = -74795892476178575122683 - 63425371988. +-4743957303476076555871972011603804 = -74795892476178575122683 * 63425371988. +74795892476178575122683 = -(-74795892476178575122683). +-74795892476178575122683 = +(-74795892476178575122683). +-1179274005524 = -74795892476178575122683 div 63425371988. +-40108260971 = -74795892476178575122683 rem 63425371988. +36577484548 = -74795892476178575122683 band 63425371988. +-74795892476151727235243 = -74795892476178575122683 bor 63425371988. +-74795892476188304719791 = -74795892476178575122683 bxor 63425371988. +74795892476178575122682 = bnot(-74795892476178575122683). +-1168685819940290236292 = -74795892476178575122683 bsl -6. +-4786937118475428807851712 = -74795892476178575122683 bsr -6. +-22437499697211126968661233906 = -22437499697211126969325683753 + 664449847. +-22437499697211126969990133600 = -22437499697211126969325683753 - 664449847. +-14908593240874479641466024262851235791 = -22437499697211126969325683753 * 664449847. +22437499697211126969325683753 = -(-22437499697211126969325683753). +-22437499697211126969325683753 = +(-22437499697211126969325683753). +-33768537683493705386 = -22437499697211126969325683753 div 664449847. +-134907811 = -22437499697211126969325683753 rem 664449847. +546452247 = -22437499697211126969325683753 band 664449847. +-22437499697211126969207686153 = -22437499697211126969325683753 bor 664449847. +-22437499697211126969754138400 = -22437499697211126969325683753 bxor 664449847. +22437499697211126969325683752 = bnot(-22437499697211126969325683753). +-1187832 = -22437499697211126969325683753 bsl -74. +-423832386118030556385499827621469560121596001124352 = -22437499697211126969325683753 bsr -74. +83166332774953742129752170768 = -2557145728214 + 83166332774953744686897898982. +-83166332774953747244043627196 = -2557145728214 - 83166332774953744686897898982. +-212668432586696948837543761316992999278148 = -2557145728214 * 83166332774953744686897898982. +2557145728214 = -(-2557145728214). +-2557145728214 = +(-2557145728214). +0 = -2557145728214 div 83166332774953744686897898982. +-2557145728214 = -2557145728214 rem 83166332774953744686897898982. +83166332774953742130305835298 = -2557145728214 band 83166332774953744686897898982. +-553664530 = -2557145728214 bor 83166332774953744686897898982. +-83166332774953742130859499828 = -2557145728214 bxor 83166332774953744686897898982. +2557145728213 = bnot(-2557145728214). +-75 = -2557145728214 bsl -35. +-87862858190281875914752 = -2557145728214 bsr -35. +72922571214 = -362 + 72922571576. +-72922571938 = -362 - 72922571576. +-26397970910512 = -362 * 72922571576. +362 = -(-362). +-362 = +(-362). +0 = -362 div 72922571576. +-362 = -362 rem 72922571576. +72922571280 = -362 band 72922571576. +-66 = -362 bor 72922571576. +-72922571346 = -362 bxor 72922571576. +361 = bnot(-362). +-6890241547122655599781102391427379235424207270408970165480824487326342629018449705258891902049390066092891366554238159926586366193756875087619592580596055738027973686297350071900831748608201993561940337577103619438035520408189345176484733649999542093444612200632321234460199120267720523776 = -362 bsl 951. +-1 = -362 bsr 951. +-93189639659574845625544558 = -93189639659574846354398755 + 728854197. +-93189639659574847083252952 = -93189639659574846354398755 - 728854197. +-67921659982798778001033681993324735 = -93189639659574846354398755 * 728854197. +93189639659574846354398755 = -(-93189639659574846354398755). +-93189639659574846354398755 = +(-93189639659574846354398755). +-127857725239352427 = -93189639659574846354398755 div 728854197. +-373312636 = -93189639659574846354398755 rem 728854197. +90261 = -93189639659574846354398755 band 728854197. +-93189639659574845625634819 = -93189639659574846354398755 bor 728854197. +-93189639659574845625725080 = -93189639659574846354398755 bxor 728854197. +93189639659574846354398754 = bnot(-93189639659574846354398755). +-10931606062726626168689879712279756080799076594515029339699505607773757758484265826434794126786089188471648933174161746396893256718020099226297769133138659324465250832140453386754272464958470824443196446258559494628169675724271919797628793512473184775801897351832646076025882542080 = -93189639659574846354398755 bsl 844. +-1 = -93189639659574846354398755 bsr 844. +776716499568896236748367 = 776716499568896236753549 + -5182. +776716499568896236758731 = 776716499568896236753549 - -5182. +-4024944900766020298856890918 = 776716499568896236753549 * -5182. +-776716499568896236753549 = -(776716499568896236753549). +776716499568896236753549 = +(776716499568896236753549). +-149887398604572797520 = 776716499568896236753549 div -5182. +4909 = 776716499568896236753549 rem -5182. +776716499568896236749440 = 776716499568896236753549 band -5182. +-1073 = 776716499568896236753549 bor -5182. +-776716499568896236750513 = 776716499568896236753549 bxor -5182. +-776716499568896236753550 = bnot(776716499568896236753549). +3416035291045895614130141354939908096 = 776716499568896236753549 bsl 42. +176604885284 = 776716499568896236753549 bsr 42. +8784691884057442103417 = 8698434224582283691994 + 86257659475158411423. +8612176565107125280571 = 8698434224582283691994 - 86257659475158411423. +750306577311082232165252216883388463247462 = 8698434224582283691994 * 86257659475158411423. +-8698434224582283691994 = -(8698434224582283691994). +8698434224582283691994 = +(8698434224582283691994). +100 = 8698434224582283691994 div 86257659475158411423. +72668277066442549694 = 8698434224582283691994 rem 86257659475158411423. +83658937330337054874 = 8698434224582283691994 band 86257659475158411423. +8701032946727105048543 = 8698434224582283691994 bor 86257659475158411423. +8617374009396767993669 = 8698434224582283691994 bxor 86257659475158411423. +-8698434224582283691995 = bnot(8698434224582283691994). +31644719363 = 8698434224582283691994 bsl -38. +2391007393343233773958935489806336 = 8698434224582283691994 bsr -38. +-889414884063465 = -482757798149 + -888932126265316. +888449368467167 = -482757798149 - -888932126265316. +429138915979752802747700084 = -482757798149 * -888932126265316. +482757798149 = -(-482757798149). +-482757798149 = +(-482757798149). +0 = -482757798149 div -888932126265316. +-482757798149 = -482757798149 rem -888932126265316. +-888933267271656 = -482757798149 band -888932126265316. +-481616791809 = -482757798149 bor -888932126265316. +888451650479847 = -482757798149 bxor -888932126265316. +482757798148 = bnot(-482757798149). +-120689449538 = -482757798149 bsl -2. +-1931031192596 = -482757798149 bsr -2. +-9311465532747505012879235860 = -9311465532741592568295336441 + -5912444583899419. +-9311465532735680123711437022 = -9311465532741592568295336441 - -5912444583899419. +55053523957224147137203729930936572309427779 = -9311465532741592568295336441 * -5912444583899419. +9311465532741592568295336441 = -(-9311465532741592568295336441). +-9311465532741592568295336441 = +(-9311465532741592568295336441). +1574892652372 = -9311465532741592568295336441 div -5912444583899419. +-1770692915564573 = -9311465532741592568295336441 rem -5912444583899419. +-9311465532747503817737468411 = -9311465532741592568295336441 band -5912444583899419. +-1195141767449 = -9311465532741592568295336441 bor -5912444583899419. +9311465532747502622595700962 = -9311465532741592568295336441 bxor -5912444583899419. +9311465532741592568295336440 = bnot(-9311465532741592568295336441). +-5496519092276855218107774179961766736959207636992 = -9311465532741592568295336441 bsl 69. +-15774237 = -9311465532741592568295336441 bsr 69. +-336594717611075159231967 = -4815737711246539 + -336594712795337447985428. +336594707979599736738889 = -4815737711246539 - -336594712795337447985428. +1620951851814704497131776297164187433692 = -4815737711246539 * -336594712795337447985428. +4815737711246539 = -(-4815737711246539). +-4815737711246539 = +(-4815737711246539). +0 = -4815737711246539 div -336594712795337447985428. +-4815737711246539 = -4815737711246539 rem -336594712795337447985428. +-336594717584535246896604 = -4815737711246539 band -336594712795337447985428. +-26539912335363 = -4815737711246539 bor -336594712795337447985428. +336594717557995334561241 = -4815737711246539 bxor -336594712795337447985428. +4815737711246538 = bnot(-4815737711246539). +-616414427039556992 = -4815737711246539 bsl 7. +-37622950869114 = -4815737711246539 bsr 7. +-841542 = -21913 + -819629. +797716 = -21913 - -819629. +17960530277 = -21913 * -819629. +21913 = -(-21913). +-21913 = +(-21913). +0 = -21913 div -819629. +-21913 = -21913 rem -819629. +-841149 = -21913 band -819629. +-393 = -21913 bor -819629. +840756 = -21913 bxor -819629. +21912 = bnot(-21913). +-86 = -21913 bsl -8. +-5609728 = -21913 bsr -8. +751693196175252841486165556 = -658945832828833 + 751693196175911787318994389. +-751693196176570733151823222 = -658945832828833 - 751693196175911787318994389. +-495325099185903537919591301481900724418037 = -658945832828833 * 751693196175911787318994389. +658945832828833 = -(-658945832828833). +-658945832828833 = +(-658945832828833). +0 = -658945832828833 div 751693196175911787318994389. +-658945832828833 = -658945832828833 rem 751693196175911787318994389. +751693196175271868196012117 = -658945832828833 band 751693196175911787318994389. +-19026709846561 = -658945832828833 bor 751693196175911787318994389. +-751693196175290894905858678 = -658945832828833 bxor 751693196175911787318994389. +658945832828832 = bnot(-658945832828833). +-42172533301045312 = -658945832828833 bsl 6. +-10296028637951 = -658945832828833 bsr 6. +8881452937194234543364865475 = -47862 + 8881452937194234543364913337. +-8881452937194234543364961199 = -47862 - 8881452937194234543364913337. +-425084100479990453714531482135494 = -47862 * 8881452937194234543364913337. +47862 = -(-47862). +-47862 = +(-47862). +0 = -47862 div 8881452937194234543364913337. +-47862 = -47862 rem 8881452937194234543364913337. +8881452937194234543364898824 = -47862 band 8881452937194234543364913337. +-33349 = -47862 bor 8881452937194234543364913337. +-8881452937194234543364932173 = -47862 bxor 8881452937194234543364913337. +47861 = bnot(-47862). +-1 = -47862 bsl -657. +-28621869264487515102197023426743807953081427927227508378485563364697061202715176740185177977686855507798311334158188612511882646044602690892250333326153431839947747374429765768428457110969640540820209664 = -47862 bsr -657. +43246692744888958054081193 = -4463469462784332 + 43246692749352427516865525. +-43246692753815896979649857 = -4463469462784332 - 43246692749352427516865525. +-193030292453151145514582848977255720954300 = -4463469462784332 * 43246692749352427516865525. +4463469462784332 = -(-4463469462784332). +-4463469462784332 = +(-4463469462784332). +0 = -4463469462784332 div 43246692749352427516865525. +-4463469462784332 = -4463469462784332 rem 43246692749352427516865525. +43246692745550864171672244 = -4463469462784332 band 43246692749352427516865525. +-661906117591051 = -4463469462784332 bor 43246692749352427516865525. +-43246692746212770289263295 = -4463469462784332 bxor 43246692749352427516865525. +4463469462784331 = bnot(-4463469462784332). +-16 = -4463469462784332 bsl -48. +-1256354963085944097420494241792 = -4463469462784332 bsr -48. +8728675682299444845504227424 = 3328234963656 + 8728675682299441517269263768. +-8728675682299438189034300112 = 3328234963656 - 8728675682299441517269263768. +29051083592242892740737765593255357615808 = 3328234963656 * 8728675682299441517269263768. +-3328234963656 = -(3328234963656). +3328234963656 = +(3328234963656). +0 = 3328234963656 div 8728675682299441517269263768. +3328234963656 = 3328234963656 rem 8728675682299441517269263768. +1100182847624 = 3328234963656 band 8728675682299441517269263768. +8728675682299443745321379800 = 3328234963656 bor 8728675682299441517269263768. +8728675682299442645138532176 = 3328234963656 bxor 8728675682299441517269263768. +-3328234963657 = bnot(3328234963656). +0 = 3328234963656 bsl -976. +2125640160021589754437853056555184807143885696198386054840467658580619821374871238208694261565718427120235436218054118816956979200437397103127510222131217940910349101057302546832028585912956319511017564357863535791436478822874955160912187456194118518427198621138185494324184783655387790473827510562865545216 = 3328234963656 bsr -976. +-82858148667443555890 = -93416 + -82858148667443462474. +82858148667443369058 = -93416 - -82858148667443462474. +7740276815917898490471184 = -93416 * -82858148667443462474. +93416 = -(-93416). +-93416 = +(-93416). +0 = -93416 div -82858148667443462474. +-93416 = -93416 rem -82858148667443462474. +-82858148667443473904 = -93416 band -82858148667443462474. +-81986 = -93416 bor -82858148667443462474. +82858148667443391918 = -93416 bxor -82858148667443462474. +93415 = bnot(-93416). +-747328 = -93416 bsl 3. +-11677 = -93416 bsr 3. +-69522286132708825661355059 = -6296125933876397422 + -69522279836582891784957637. +69522273540456957908560215 = -6296125933876397422 - -69522279836582891784957637. +437721029061321693891748265271742172446011814 = -6296125933876397422 * -69522279836582891784957637. +6296125933876397422 = -(-6296125933876397422). +-6296125933876397422 = +(-6296125933876397422). +0 = -6296125933876397422 div -69522279836582891784957637. +-6296125933876397422 = -6296125933876397422 rem -69522279836582891784957637. +-69522279836587466206212078 = -6296125933876397422 band -69522279836582891784957637. +-6296121359455142981 = -6296125933876397422 bor -69522279836582891784957637. +69522273540466106751069097 = -6296125933876397422 bxor -69522279836582891784957637. +6296125933876397421 = bnot(-6296125933876397422). +-29959826309054960899492441143257086457558738752300529629065745032858510795396227815951096336645313085285082382949010591123047750614938649536436354908253490458588459860438104999605715265971851389712439168805885079103840928811819820835717902702278465473672638927765675383076896434542926217646211947418353664 = -6296125933876397422 bsl 949. +-1 = -6296125933876397422 bsr 949. +-8790853496198 = 4658928385 + -8795512424583. +8800171352968 = 4658928385 - -8795512424583. +-40977662495509910488455 = 4658928385 * -8795512424583. +-4658928385 = -(4658928385). +4658928385 = +(4658928385). +0 = 4658928385 div -8795512424583. +4658928385 = 4658928385 rem -8795512424583. +9507585 = 4658928385 band -8795512424583. +-8790863003783 = 4658928385 bor -8795512424583. +-8790872511368 = 4658928385 bxor -8795512424583. +-4658928386 = bnot(4658928385). +582366048 = 4658928385 bsl -3. +37271427080 = 4658928385 bsr -3. +7715926329340651 = 7711677977654284 + 4248351686367. +7707429625967917 = 7711677977654284 - 4248351686367. +32761920141086833574321946228 = 7711677977654284 * 4248351686367. +-7711677977654284 = -(7711677977654284). +7711677977654284 = +(7711677977654284). +1815 = 7711677977654284 div 4248351686367. +919666898179 = 7711677977654284 rem 4248351686367. +1752891536396 = 7711677977654284 band 4248351686367. +7714173437804255 = 7711677977654284 bor 4248351686367. +7712420546267859 = 7711677977654284 bxor 4248351686367. +-7711677977654285 = bnot(7711677977654284). +60247484200424 = 7711677977654284 bsl -7. +987094781139748352 = 7711677977654284 bsr -7. +-42642321093453 = 2585512 + -42642323678965. +42642326264477 = 2585512 - -42642323678965. +-110252239579848155080 = 2585512 * -42642323678965. +-2585512 = -(2585512). +2585512 = +(2585512). +0 = 2585512 div -42642323678965. +2585512 = 2585512 rem -42642323678965. +2183432 = 2585512 band -42642323678965. +-42642323276885 = 2585512 bor -42642323678965. +-42642325460317 = 2585512 bxor -42642323678965. +-2585513 = bnot(2585512). +325658762403878241163952527518051310623588082226349026899363505534404205118952466218333127046730115696891637885047489472578634310547091362187317737408559758990182083158406170172516194279339952578517625445121509111687082511722725843073735533362617019272189110606687633408 = 2585512 bsl 874. +0 = 2585512 bsr 874. +-767284617701761748962633 = -39272154248625298665 + -767245345547513123663968. +767206073393264498365303 = -39272154248625298665 - -767245345547513123663968. +30131377556881752895633973866033123099002720 = -39272154248625298665 * -767245345547513123663968. +39272154248625298665 = -(-39272154248625298665). +-39272154248625298665 = +(-39272154248625298665). +0 = -39272154248625298665 div -767245345547513123663968. +-39272154248625298665 = -39272154248625298665 rem -767245345547513123663968. +-767282311269246790663424 = -39272154248625298665 band -767245345547513123663968. +-2306432514958299209 = -39272154248625298665 bor -767245345547513123663968. +767280004836731832364215 = -39272154248625298665 bxor -767245345547513123663968. +39272154248625298664 = bnot(-39272154248625298665). +-76703426266846287 = -39272154248625298665 bsl -9. +-20107342975296152916480 = -39272154248625298665 bsr -9. +-9239493198773203875387030 = -9239493198773198132818179 + -5742568851. +-9239493198773192390249328 = -9239493198773198132818179 - -5742568851. +53058425842301319011173035571942329 = -9239493198773198132818179 * -5742568851. +9239493198773198132818179 = -(-9239493198773198132818179). +-9239493198773198132818179 = +(-9239493198773198132818179). +1608947744207585 = -9239493198773198132818179 div -5742568851. +-4833883344 = -9239493198773198132818179 rem -5742568851. +-9239493198773203808269715 = -9239493198773198132818179 band -5742568851. +-67117315 = -9239493198773198132818179 bor -5742568851. +9239493198773203741152400 = -9239493198773198132818179 bxor -5742568851. +9239493198773198132818178 = bnot(-9239493198773198132818179). +-295663782360742340250181728 = -9239493198773198132818179 bsl 5. +-288734162461662441650569 = -9239493198773198132818179 bsr 5. +-51767695721771121252643955124 = -51767695721771121252643961599 + 6475. +-51767695721771121252643968074 = -51767695721771121252643961599 - 6475. +-335195829798468010110869651353525 = -51767695721771121252643961599 * 6475. +51767695721771121252643961599 = -(-51767695721771121252643961599). +-51767695721771121252643961599 = +(-51767695721771121252643961599). +-7995010922281254247512580 = -51767695721771121252643961599 div 6475. +-6099 = -51767695721771121252643961599 rem 6475. +257 = -51767695721771121252643961599 band 6475. +-51767695721771121252643955381 = -51767695721771121252643961599 bor 6475. +-51767695721771121252643955638 = -51767695721771121252643961599 bxor 6475. +51767695721771121252643961598 = bnot(-51767695721771121252643961599). +-1 = -51767695721771121252643961599 bsl -96. +-4101459409633469070626883473116985513501536515007147147264 = -51767695721771121252643961599 bsr -96. +-71488425765717485811 = 2 + -71488425765717485813. +71488425765717485815 = 2 - -71488425765717485813. +-142976851531434971626 = 2 * -71488425765717485813. +-2 = -(2). +2 = +(2). +0 = 2 div -71488425765717485813. +2 = 2 rem -71488425765717485813. +2 = 2 band -71488425765717485813. +-71488425765717485813 = 2 bor -71488425765717485813. +-71488425765717485815 = 2 bxor -71488425765717485813. +-3 = bnot(2). +0 = 2 bsl -9. +1024 = 2 bsr -9. +-29853310 = 49 + -29853359. +29853408 = 49 - -29853359. +-1462814591 = 49 * -29853359. +-49 = -(49). +49 = +(49). +0 = 49 div -29853359. +49 = 49 rem -29853359. +17 = 49 band -29853359. +-29853327 = 49 bor -29853359. +-29853344 = 49 bxor -29853359. +-50 = bnot(49). +0 = 49 bsl -822. +1370416300786399510758320715576237388716176972105822240178350620520744273693644827937420829126373818746131460890362291292622506032320894002267388941442055079497198087002911516612376232238740195347663047268901872193672458131572403903469316961149648896 = 49 bsr -822. +-3327259672827942138 = 38 + -3327259672827942176. +3327259672827942214 = 38 - -3327259672827942176. +-126435867567461802688 = 38 * -3327259672827942176. +-38 = -(38). +38 = +(38). +0 = 38 div -3327259672827942176. +38 = 38 rem -3327259672827942176. +32 = 38 band -3327259672827942176. +-3327259672827942170 = 38 bor -3327259672827942176. +-3327259672827942202 = 38 bxor -3327259672827942176. +-39 = bnot(38). +10952754293765046272 = 38 bsl 58. +0 = 38 bsr 58. +-6166638483332631225207873 = -6166638483332631677652215 + 452444342. +-6166638483332632130096557 = -6166638483332631677652215 - 452444342. +-2790060690943310506523712520517530 = -6166638483332631677652215 * 452444342. +6166638483332631677652215 = -(-6166638483332631677652215). +-6166638483332631677652215 = +(-6166638483332631677652215). +-13629606806603919 = -6166638483332631677652215 div 452444342. +-291075917 = -6166638483332631677652215 rem 452444342. +310870016 = -6166638483332631677652215 band 452444342. +-6166638483332631536077889 = -6166638483332631677652215 bor 452444342. +-6166638483332631846947905 = -6166638483332631677652215 bxor 452444342. +6166638483332631677652214 = bnot(-6166638483332631677652215). +-1 = -6166638483332631677652215 bsl -996. +-4129753882685615072570641438967458335229779666029661176613271197538250890449055225405454861443951408827738251305872557217168543348545877943992188684690076608466334151476719612408546067060287806744603782814736963222494649921816478038076842248135088239975552993497178634462091574277794817071167406424900701076341124126463754240 = -6166638483332631677652215 bsr -996. +-8945229019521027315 = -63946584418 + -8945228955574442897. +8945228891627858479 = -63946584418 - -8945228955574442897. +572016838545979084396330978946 = -63946584418 * -8945228955574442897. +63946584418 = -(-63946584418). +-63946584418 = +(-63946584418). +0 = -63946584418 div -8945228955574442897. +-63946584418 = -63946584418 rem -8945228955574442897. +-8945228992618691570 = -63946584418 band -8945228955574442897. +-26902335745 = -63946584418 bor -8945228955574442897. +8945228965716355825 = -63946584418 bxor -8945228955574442897. +63946584417 = bnot(-63946584418). +-2046290701376 = -63946584418 bsl 5. +-1998330764 = -63946584418 bsr 5. +67443671255351964 = 6213841 + 67443671249138123. +-67443671242924282 = 6213841 - 67443671249138123. +419084249598415683360443 = 6213841 * 67443671249138123. +-6213841 = -(6213841). +6213841 = +(6213841). +0 = 6213841 div 67443671249138123. +6213841 = 6213841 rem 67443671249138123. +397505 = 6213841 band 67443671249138123. +67443671254954459 = 6213841 bor 67443671249138123. +67443671254556954 = 6213841 bxor 67443671249138123. +-6213842 = bnot(6213841). +24272 = 6213841 bsl -8. +1590743296 = 6213841 bsr -8. +82342884782 = 82345722295 + -2837513. +82348559808 = 82345722295 - -2837513. +-233657057506452335 = 82345722295 * -2837513. +-82345722295 = -(82345722295). +82345722295 = +(82345722295). +-29020 = 82345722295 div -2837513. +1095035 = 82345722295 rem -2837513. +82343625143 = 82345722295 band -2837513. +-740361 = 82345722295 bor -2837513. +-82344365504 = 82345722295 bxor -2837513. +-82345722296 = bnot(82345722295). +0 = 82345722295 bsl -75. +3110933431788797435617493972418560 = 82345722295 bsr -75. +43572240502045 = -743398 + 43572241245443. +-43572241988841 = -743398 - 43572241245443. +-32391516997379835314 = -743398 * 43572241245443. +743398 = -(-743398). +-743398 = +(-743398). +0 = -743398 div 43572241245443. +-743398 = -743398 rem 43572241245443. +43572241113090 = -743398 band 43572241245443. +-611045 = -743398 bor 43572241245443. +-43572241724135 = -743398 bxor 43572241245443. +743397 = bnot(-743398). +-47577472 = -743398 bsl 6. +-11616 = -743398 bsr 6. +-91594137246897918174 = -833 + -91594137246897917341. +91594137246897916508 = -833 - -91594137246897917341. +76297916326665965145053 = -833 * -91594137246897917341. +833 = -(-833). +-833 = +(-833). +0 = -833 div -91594137246897917341. +-833 = -833 rem -91594137246897917341. +-91594137246897917917 = -833 band -91594137246897917341. +-257 = -833 bor -91594137246897917341. +91594137246897917660 = -833 bxor -91594137246897917341. +832 = bnot(-833). +-1 = -833 bsl -799. +-2777228011294459305154258270835403872510791841244575748805041378599721509551043757788676511663002362094430307762164944645712685888940715555971337795795790714198633131867587063599872106082270541299613929220596769725374196557608946127769754927104 = -833 bsr -799. +7785281615558743240165 = 755344292 + 7785281615557987895873. +-7785281615557232551581 = 755344292 - 7785281615557987895873. +5880568029924264552152760906916 = 755344292 * 7785281615557987895873. +-755344292 = -(755344292). +755344292 = +(755344292). +0 = 755344292 div 7785281615557987895873. +755344292 = 755344292 rem 7785281615557987895873. +16876032 = 755344292 band 7785281615557987895873. +7785281615558726364133 = 755344292 bor 7785281615557987895873. +7785281615558709488101 = 755344292 bxor 7785281615557987895873. +-755344293 = bnot(755344292). +29220966953514617177951386199916544 = 755344292 bsl 85. +0 = 755344292 bsr 85. +-1078320760604 = -4824745155583 + 3746424394979. +-8571169550562 = -4824745155583 - 3746424394979. +-18075542950432901999017757 = -4824745155583 * 3746424394979. +4824745155583 = -(-4824745155583). +-4824745155583 = +(-4824745155583). +-1 = -4824745155583 div 3746424394979. +-1078320760604 = -4824745155583 rem 3746424394979. +3332899013633 = -4824745155583 band 3746424394979. +-4411219774237 = -4824745155583 bor 3746424394979. +-7744118787870 = -4824745155583 bxor 3746424394979. +4824745155582 = bnot(-4824745155583). +-6344703802175932826948506277387853831652433096072652876345722969499346964981655993272881899870798551447793487830423204642644396774153846137488341278160903583437198477435542964519758669496804762864416770266392624939298455552 = -4824745155583 bsl 698. +-1 = -4824745155583 bsr 698. +736594418215962290005038759664 = 736594418215962289947266895286 + 57771864378. +736594418215962289889495030908 = 736594418215962289947266895286 - 57771864378. +42554432830764386129595815846231919522108 = 736594418215962289947266895286 * 57771864378. +-736594418215962289947266895286 = -(736594418215962289947266895286). +736594418215962289947266895286 = +(736594418215962289947266895286). +12750054479745394689 = 736594418215962289947266895286 div 57771864378. +4277406844 = 736594418215962289947266895286 rem 57771864378. +57747210546 = 736594418215962289947266895286 band 57771864378. +736594418215962289947291549118 = 736594418215962289947266895286 bor 57771864378. +736594418215962289889544338572 = 736594418215962289947266895286 bxor 57771864378. +-736594418215962289947266895287 = bnot(736594418215962289947266895286). +13913875168207705462638560218105114542296559700148224 = 736594418215962289947266895286 bsl 74. +38994983 = 736594418215962289947266895286 bsr 74. +-44499666734315603021609175 = -44267334142723866234955437 + -232332591591736786653738. +-44035001551132129448301699 = -44267334142723866234955437 - -232332591591736786653738. +10284744464236409699247335826909733008312779473506 = -44267334142723866234955437 * -232332591591736786653738. +44267334142723866234955437 = -(-44267334142723866234955437). +-44267334142723866234955437 = +(-44267334142723866234955437). +190 = -44267334142723866234955437 div -232332591591736786653738. +-124141740293876770745217 = -44267334142723866234955437 rem -232332591591736786653738. +-44418486790699506364036782 = -44267334142723866234955437 band -232332591591736786653738. +-81179943616096657572393 = -44267334142723866234955437 bor -232332591591736786653738. +44337306847083409706464389 = -44267334142723866234955437 bxor -232332591591736786653738. +44267334142723866234955436 = bnot(-44267334142723866234955437). +-19344603412483138584124909315899351993406026847258365156654530346044019592419283545366730486787483901772466875019849611292165184086245659597430481191845721885258321204649825128992477334294813436320376000188342502728496927502124171690494640260046529660954126810644041695232 = -44267334142723866234955437 bsl 816. +-1 = -44267334142723866234955437 bsr 816. +683857175479606 = 683857175479682 + -76. +683857175479758 = 683857175479682 - -76. +-51973145336455832 = 683857175479682 * -76. +-683857175479682 = -(683857175479682). +683857175479682 = +(683857175479682). +-8998120729995 = 683857175479682 div -76. +62 = 683857175479682 rem -76. +683857175479680 = 683857175479682 band -76. +-74 = 683857175479682 bor -76. +-683857175479754 = 683857175479682 bxor -76. +-683857175479683 = bnot(683857175479682). +0 = 683857175479682 bsl -619. +1487759472876019611292223358074497985975273879482222010497134415479575860865563804521231385258548213499430324053331578407367628766429304314628378275020045407624205785928797259522281156909858045523132416 = 683857175479682 bsr -619. +-7584278372166956 = -7584278372166953 + -3. +-7584278372166950 = -7584278372166953 - -3. +22752835116500859 = -7584278372166953 * -3. +7584278372166953 = -(-7584278372166953). +-7584278372166953 = +(-7584278372166953). +2528092790722317 = -7584278372166953 div -3. +-2 = -7584278372166953 rem -3. +-7584278372166955 = -7584278372166953 band -3. +-1 = -7584278372166953 bor -3. +7584278372166954 = -7584278372166953 bxor -3. +7584278372166952 = bnot(-7584278372166953). +-237008699130218 = -7584278372166953 bsl -5. +-242696907909342496 = -7584278372166953 bsr -5. +700475563613494766961192 = 699891966453749538575625 + 583597159745228385567. +699308369294004310190058 = 699891966453749538575625 - 583597159745228385567. +408454963750910895841936347455859207488004375 = 699891966453749538575625 * 583597159745228385567. +-699891966453749538575625 = -(699891966453749538575625). +699891966453749538575625 = +(699891966453749538575625). +1199 = 699891966453749538575625 div 583597159745228385567. +158971919220704280792 = 699891966453749538575625 rem 583597159745228385567. +389687613701390075145 = 699891966453749538575625 band 583597159745228385567. +700085875999793376886047 = 699891966453749538575625 bor 583597159745228385567. +699696188386091986810902 = 699891966453749538575625 bxor 583597159745228385567. +-699891966453749538575626 = bnot(699891966453749538575625). +5214601505203169 = 699891966453749538575625 bsl -27. +93937909582874480148668743680000 = 699891966453749538575625 bsr -27. +24163917278717181820 = -397919 + 24163917278717579739. +-24163917278717977658 = -397919 - 24163917278717579739. +-9615281799630020612163141 = -397919 * 24163917278717579739. +397919 = -(-397919). +-397919 = +(-397919). +0 = -397919 div 24163917278717579739. +-397919 = -397919 rem 24163917278717579739. +24163917278717444481 = -397919 band 24163917278717579739. +-262661 = -397919 bor 24163917278717579739. +-24163917278717707142 = -397919 bxor 24163917278717579739. +397918 = bnot(-397919). +-881720008260862467535648094417617143671022248542464649309238318334728166992382627601504073345655260786923942524000700776672122040870760879424839487674361120308837255626935937373935928217849017914636001805242153319122303273815123985408819695181545132002338731761585908602058714382336 = -397919 bsl 918. +-1 = -397919 bsr 918. +-2325699978272500 = -757 + -2325699978271743. +2325699978270986 = -757 - -2325699978271743. +1760554883551709451 = -757 * -2325699978271743. +757 = -(-757). +-757 = +(-757). +0 = -757 div -2325699978271743. +-757 = -757 rem -2325699978271743. +-2325699978271743 = -757 band -2325699978271743. +-757 = -757 bor -2325699978271743. +2325699978270986 = -757 bxor -2325699978271743. +756 = bnot(-757). +-1 = -757 bsl -877. +-762784881724736388184969362605672971982512332552612289907200349298843658896333157772319531835473043892418893832961361713245271878325525191685977948563471335830018462728971192771396177065000182871130646346122493022804369769311775658227284340604108071713601504782843904 = -757 bsr -877. +-399326552934552554555 = -399326552934552554837 + 282. +-399326552934552555119 = -399326552934552554837 - 282. +-112610087927543820464034 = -399326552934552554837 * 282. +399326552934552554837 = -(-399326552934552554837). +-399326552934552554837 = +(-399326552934552554837). +-1416051606150895584 = -399326552934552554837 div 282. +-149 = -399326552934552554837 rem 282. +10 = -399326552934552554837 band 282. +-399326552934552554565 = -399326552934552554837 bor 282. +-399326552934552554575 = -399326552934552554837 bxor 282. +399326552934552554836 = bnot(-399326552934552554837). +-162519239404282077726356668430744933325304730894253957182797269749815524173310489155599580175893087324766269535394202666586959435660185747865985481001922616246731215114933426566027267436359691332683403034291364290584270445935905624013135372400880425231187968 = -399326552934552554837 bsl 786. +-1 = -399326552934552554837 bsr 786. +7788556563963559887277654637 = 7788556563963286199292257816 + 273687985396821. +7788556563963012511306860995 = 7788556563963286199292257816 - 273687985396821. +2131634355140298218131081660650893798802936 = 7788556563963286199292257816 * 273687985396821. +-7788556563963286199292257816 = -(7788556563963286199292257816). +7788556563963286199292257816 = +(7788556563963286199292257816). +28457794932688 = 7788556563963286199292257816 div 273687985396821. +46202628072968 = 7788556563963286199292257816 rem 273687985396821. +220625256055824 = 7788556563963286199292257816 band 273687985396821. +7788556563963339262021598813 = 7788556563963286199292257816 bor 273687985396821. +7788556563963118636765542989 = 7788556563963286199292257816 bxor 273687985396821. +-7788556563963286199292257817 = bnot(7788556563963286199292257816). +1122449294055010765489568052730189407481495552 = 7788556563963286199292257816 bsl 57. +54043967661 = 7788556563963286199292257816 bsr 57. +455741584345907566712 = 455741584345945741559 + -38174847. +455741584345983916406 = 455741584345945741559 - -38174847. +-17397865253944073754316366473 = 455741584345945741559 * -38174847. +-455741584345945741559 = -(455741584345945741559). +455741584345945741559 = +(455741584345945741559). +-11938268785882 = 455741584345945741559 div -38174847. +24631505 = 455741584345945741559 rem -38174847. +455741584345941416065 = 455741584345945741559 band -38174847. +-33849353 = 455741584345945741559 bor -38174847. +-455741584345975265418 = 455741584345945741559 bxor -38174847. +-455741584345945741560 = bnot(455741584345945741559). +233339691185124219678208 = 455741584345945741559 bsl 9. +890120281925675276 = 455741584345945741559 bsr 9. +-374898793368034 = -374967657234849 + 68863866815. +-375036521101664 = -374967657234849 - 68863866815. +-25821722807753212712635935 = -374967657234849 * 68863866815. +374967657234849 = -(-374967657234849). +-374967657234849 = +(-374967657234849). +-5445 = -374967657234849 div 68863866815. +-3902427174 = -374967657234849 rem 68863866815. +68863669791 = -374967657234849 band 68863866815. +-374967657037825 = -374967657234849 bor 68863866815. +-375036520707616 = -374967657234849 bxor 68863866815. +374967657234848 = bnot(-374967657234849). +-5858869644295 = -374967657234849 bsl -6. +-23997930063030336 = -374967657234849 bsr -6. +695698116237678489407423938 = 695698116237678482758846255 + 6648577683. +695698116237678476110268572 = 695698116237678482758846255 - 6648577683. +4625402969722969084199765481821127165 = 695698116237678482758846255 * 6648577683. +-695698116237678482758846255 = -(695698116237678482758846255). +695698116237678482758846255 = +(695698116237678482758846255). +104638638428868077 = 695698116237678482758846255 div 6648577683. +3065520664 = 695698116237678482758846255 rem 6648577683. +4295493123 = 695698116237678482758846255 band 6648577683. +695698116237678485111930815 = 695698116237678482758846255 bor 6648577683. +695698116237678480816437692 = 695698116237678482758846255 bxor 6648577683. +-695698116237678482758846256 = bnot(695698116237678482758846255). +5435141533106863146553486 = 695698116237678482758846255 bsl -7. +89049358878422845793132320640 = 695698116237678482758846255 bsr -7. +867155941797334727149668788 = -2397633985559 + 867155941797337124783654347. +-867155941797339522417639906 = -2397633985559 - 867155941797337124783654347. +-2079122556832717644348186887614245574973 = -2397633985559 * 867155941797337124783654347. +2397633985559 = -(-2397633985559). +-2397633985559 = +(-2397633985559). +0 = -2397633985559 div 867155941797337124783654347. +-2397633985559 = -2397633985559 rem 867155941797337124783654347. +867155941797334891131568585 = -2397633985559 band 867155941797337124783654347. +-163981899797 = -2397633985559 bor 867155941797337124783654347. +-867155941797335055113468382 = -2397633985559 bxor 867155941797337124783654347. +2397633985558 = bnot(-2397633985559). +-4682878879 = -2397633985559 bsl -9. +-1227588600606208 = -2397633985559 bsr -9. +-99391269544746942 = -999 + -99391269544745943. +99391269544744944 = -999 - -99391269544745943. +99291878275201197057 = -999 * -99391269544745943. +999 = -(-999). +-999 = +(-999). +0 = -999 div -99391269544745943. +-999 = -999 rem -99391269544745943. +-99391269544745975 = -999 band -99391269544745943. +-967 = -999 bor -99391269544745943. +99391269544745008 = -999 bxor -99391269544745943. +998 = bnot(-999). +-271670709669862569774540092593109073255558924599964104333437283359848016026107591934168749958637596868208865360261250311337591172257307920471096554899364231471046369057053606816100556734464 = -999 bsl 616. +-1 = -999 bsr 616. +51170326738252384475287511615 = -53532239445214813437776259 + 51223858977697599288725287874. +-51277391217142814102163064133 = -53532239445214813437776259 - 51223858977697599288725287874. +-2742127884102024373168869308493551385093294966177783366 = -53532239445214813437776259 * 51223858977697599288725287874. +53532239445214813437776259 = -(-53532239445214813437776259). +-53532239445214813437776259 = +(-53532239445214813437776259). +0 = -53532239445214813437776259 div 51223858977697599288725287874. +-53532239445214813437776259 = -53532239445214813437776259 rem 51223858977697599288725287874. +51223547227586499364060668480 = -53532239445214813437776259 band 51223858977697599288725287874. +-53220489334114888773156865 = -53532239445214813437776259 bor 51223858977697599288725287874. +-51276767716920614252833825345 = -53532239445214813437776259 bxor 51223858977697599288725287874. +53532239445214813437776258 = bnot(-53532239445214813437776259). +-1713031662246874030008840288 = -53532239445214813437776259 bsl 5. +-1672882482662962919930509 = -53532239445214813437776259 bsr 5. +73264835839749594226010 = 8662 + 73264835839749594217348. +-73264835839749594208686 = 8662 - 73264835839749594217348. +634620008043910985110668376 = 8662 * 73264835839749594217348. +-8662 = -(8662). +8662 = +(8662). +0 = 8662 div 73264835839749594217348. +8662 = 8662 rem 73264835839749594217348. +8580 = 8662 band 73264835839749594217348. +73264835839749594217430 = 8662 bor 73264835839749594217348. +73264835839749594208850 = 8662 bxor 73264835839749594217348. +-8663 = bnot(8662). +67 = 8662 bsl -7. +1108736 = 8662 bsr -7. +-88648668659335769732449251 = -88648668659335769732446832 + -2419. +-88648668659335769732444413 = -88648668659335769732446832 - -2419. +214441129486933226982788886608 = -88648668659335769732446832 * -2419. +88648668659335769732446832 = -(-88648668659335769732446832). +-88648668659335769732446832 = +(-88648668659335769732446832). +36646824580130537301548 = -88648668659335769732446832 div -2419. +-2220 = -88648668659335769732446832 rem -2419. +-88648668659335769732447104 = -88648668659335769732446832 band -2419. +-2147 = -88648668659335769732446832 bor -2419. +88648668659335769732444957 = -88648668659335769732446832 bxor -2419. +88648668659335769732446831 = bnot(-88648668659335769732446832). +-1 = -88648668659335769732446832 bsl -277. +-21526876367714690857102338451583587804202513123842334826095893895994143205595507487537586045998436466561122304 = -88648668659335769732446832 bsr -277. +472407689385533914110659 = -92176733159392931236298 + 564584422544926845346957. +-656761155704319776583255 = -92176733159392931236298 - 564584422544926845346957. +-52041547662873668367867286690437311862762245186 = -92176733159392931236298 * 564584422544926845346957. +92176733159392931236298 = -(-92176733159392931236298). +-92176733159392931236298 = +(-92176733159392931236298). +0 = -92176733159392931236298 div 564584422544926845346957. +-92176733159392931236298 = -92176733159392931236298 rem 564584422544926845346957. +472421606637668457948164 = -92176733159392931236298 band 564584422544926845346957. +-13917252134543837505 = -92176733159392931236298 bor 564584422544926845346957. +-472435523889803001785669 = -92176733159392931236298 bxor 564584422544926845346957. +92176733159392931236297 = bnot(-92176733159392931236298). +-197948027185855697436738379055104 = -92176733159392931236298 bsl 31. +-42923136222825 = -92176733159392931236298 bsr 31. +926565856438049866558555264 = 933124279636981428678231393 + -6558423198931562119676129. +939682702835912990797907522 = 933124279636981428678231393 - -6558423198931562119676129. +-6119823923057481252398382601992868036026185680517697 = 933124279636981428678231393 * -6558423198931562119676129. +-933124279636981428678231393 = -(933124279636981428678231393). +933124279636981428678231393 = +(933124279636981428678231393). +-142 = 933124279636981428678231393 div -6558423198931562119676129. +1828185388699607684221075 = 933124279636981428678231393 rem -6558423198931562119676129. +931552902605547407822423297 = 933124279636981428678231393 band -6558423198931562119676129. +-4987046167497541263868033 = 933124279636981428678231393 bor -6558423198931562119676129. +-936539948773044949086291330 = 933124279636981428678231393 bxor -6558423198931562119676129. +-933124279636981428678231394 = bnot(933124279636981428678231393). +108629963318465909 = 933124279636981428678231393 bsl -33. +8015476528288787976664720680111046656 = 933124279636981428678231393 bsr -33. +-272843753421484620759016887177 = -272836611788825721137484413564 + -7141632658899621532473613. +-272829470156166821515951939951 = -272836611788825721137484413564 - -7141632658899621532473613. +1948498857294595260358231217824490200133654665609286732 = -272836611788825721137484413564 * -7141632658899621532473613. +272836611788825721137484413564 = -(-272836611788825721137484413564). +-272836611788825721137484413564 = +(-272836611788825721137484413564). +38203 = -272836611788825721137484413564 div -7141632658899621532473613. +-4819320883479732394976125 = -272836611788825721137484413564 rem -7141632658899621532473613. +-272837556339268983097432947584 = -272836611788825721137484413564 band -7141632658899621532473613. +-6197082215637661583939593 = -272836611788825721137484413564 bor -7141632658899621532473613. +272831359257053345435849007991 = -272836611788825721137484413564 bxor -7141632658899621532473613. +272836611788825721137484413563 = bnot(-272836611788825721137484413564). +-1 = -272836611788825721137484413564 bsl -975. +-87126129236002257870538958730310744500573154348629344446020418054995206413443356585847042214910091639020918677712597473077059225043718786652309645154890346722009375561018953488114368585295148197269160637768429141827421422749860346865955452200127047946305111734795397098009767822432538074840838252544803626856997705431908352 = -272836611788825721137484413564 bsr -975. +542255456896764093697 = 542255456889625635573 + 7138458124. +542255456882487177449 = 542255456889625635573 - 7138458124. +3870867871517079889574745245052 = 542255456889625635573 * 7138458124. +-542255456889625635573 = -(542255456889625635573). +542255456889625635573 = +(542255456889625635573). +75962546458 = 542255456889625635573 div 7138458124. +6788110781 = 542255456889625635573 rem 7138458124. +692333060 = 542255456889625635573 band 7138458124. +542255456896071760637 = 542255456889625635573 bor 7138458124. +542255456895379427577 = 542255456889625635573 bxor 7138458124. +-542255456889625635574 = bnot(542255456889625635573). +8676087310234010169168 = 542255456889625635573 bsl 4. +33890966055601602223 = 542255456889625635573 bsr 4. +55994598326593711852577100 = -5774543 + 55994598326593711858351643. +-55994598326593711864126186 = -5774543 - 55994598326593711858351643. +-323343215804643432655661471624149 = -5774543 * 55994598326593711858351643. +5774543 = -(-5774543). +-5774543 = +(-5774543). +0 = -5774543 div 55994598326593711858351643. +-5774543 = -5774543 rem 55994598326593711858351643. +55994598326593711857820177 = -5774543 band 55994598326593711858351643. +-5243077 = -5774543 bor 55994598326593711858351643. +-55994598326593711863063254 = -5774543 bxor 55994598326593711858351643. +5774542 = bnot(-5774543). +-1443636 = -5774543 bsl -2. +-23098172 = -5774543 bsr -2. +-242182668347924615038 = -242182668347924614996 + -42. +-242182668347924614954 = -242182668347924614996 - -42. +10171672070612833829832 = -242182668347924614996 * -42. +242182668347924614996 = -(-242182668347924614996). +-242182668347924614996 = +(-242182668347924614996). +5766254008283919404 = -242182668347924614996 div -42. +-28 = -242182668347924614996 rem -42. +-242182668347924615036 = -242182668347924614996 band -42. +-2 = -242182668347924614996 bor -42. +242182668347924615034 = -242182668347924614996 bxor -42. +242182668347924614995 = bnot(-242182668347924614996). +-3874922693566793839936 = -242182668347924614996 bsl 4. +-15136416771745288438 = -242182668347924614996 bsr 4. +7797689768344356 = 7797689768344352 + 4. +7797689768344348 = 7797689768344352 - 4. +31190759073377408 = 7797689768344352 * 4. +-7797689768344352 = -(7797689768344352). +7797689768344352 = +(7797689768344352). +1949422442086088 = 7797689768344352 div 4. +0 = 7797689768344352 rem 4. +0 = 7797689768344352 band 4. +7797689768344356 = 7797689768344352 bor 4. +7797689768344356 = 7797689768344352 bxor 4. +-7797689768344353 = bnot(7797689768344352). +4942373057617620444148698860578715267472818176 = 7797689768344352 bsl 99. +0 = 7797689768344352 bsr 99. +3825348573927459346362328 = -67412241 + 3825348573927459413774569. +-3825348573927459481186810 = -67412241 - 3825348573927459413774569. +-257875319974604210519089965099129 = -67412241 * 3825348573927459413774569. +67412241 = -(-67412241). +-67412241 = +(-67412241). +0 = -67412241 div 3825348573927459413774569. +-67412241 = -67412241 rem 3825348573927459413774569. +3825348573927459413774569 = -67412241 band 3825348573927459413774569. +-67412241 = -67412241 bor 3825348573927459413774569. +-3825348573927459481186810 = -67412241 bxor 3825348573927459413774569. +67412240 = bnot(-67412241). +-1078595856 = -67412241 bsl 4. +-4213266 = -67412241 bsr 4. +4912958129896753774 = -71229483 + 4912958129967983257. +-4912958130039212740 = -71229483 - 4912958129967983257. +-349947467598266253948766131 = -71229483 * 4912958129967983257. +71229483 = -(-71229483). +-71229483 = +(-71229483). +0 = -71229483 div 4912958129967983257. +-71229483 = -71229483 rem 4912958129967983257. +4912958129899113105 = -71229483 band 4912958129967983257. +-2359331 = -71229483 bor 4912958129967983257. +-4912958129901472436 = -71229483 bxor 4912958129967983257. +71229482 = bnot(-71229483). +-1 = -71229483 bsl -762. +-1727891579105090281002224014699820654642608174830491410613854965292061717054813855570284937448861315846627197740623061370480532122428365964742753217260345878982568113105352124889753543881032588882929824556216264339246144840554599659077632 = -71229483 bsr -762. +46494293391644389 = 46494293391868173 + -223784. +46494293392091957 = 46494293391868173 - -223784. +-10404678952405827226632 = 46494293391868173 * -223784. +-46494293391868173 = -(46494293391868173). +46494293391868173 = +(46494293391868173). +-207764153790 = 46494293391868173 div -223784. +126813 = 46494293391868173 rem -223784. +46494293391868168 = 46494293391868173 band -223784. +-223779 = 46494293391868173 bor -223784. +-46494293392091947 = 46494293391868173 bxor -223784. +-46494293391868174 = bnot(46494293391868173). +0 = 46494293391868173 bsl -91. +115114294776150565191781242098022401917845504 = 46494293391868173 bsr -91. +-412781543671019436383555080573 = -8847989186169711636 + -412781543662171447197385368937. +412781543653323458011215657301 = -8847989186169711636 - -412781543662171447197385368937. +3652286634573333633165948299445552201166761850932 = -8847989186169711636 * -412781543662171447197385368937. +8847989186169711636 = -(-8847989186169711636). +-8847989186169711636 = +(-8847989186169711636). +0 = -8847989186169711636 div -412781543662171447197385368937. +-8847989186169711636 = -8847989186169711636 rem -412781543662171447197385368937. +-412781543670982818247229615484 = -8847989186169711636 band -412781543662171447197385368937. +-36618136325465089 = -8847989186169711636 bor -412781543662171447197385368937. +412781543670946200110904150395 = -8847989186169711636 bxor -412781543662171447197385368937. +8847989186169711635 = bnot(-8847989186169711636). +-250128699564397448650083420076872233779944628446086238630703601982129156400429730446574616576 = -8847989186169711636 bsl 244. +-1 = -8847989186169711636 bsr 244. +-6743223186536623446244856 = -6743223186536623446251414 + 6558. +-6743223186536623446257972 = -6743223186536623446251414 - 6558. +-44222057657307176560516773012 = -6743223186536623446251414 * 6558. +6743223186536623446251414 = -(-6743223186536623446251414). +-6743223186536623446251414 = +(-6743223186536623446251414). +-1028243852780820897568 = -6743223186536623446251414 div 6558. +-470 = -6743223186536623446251414 rem 6558. +2058 = -6743223186536623446251414 band 6558. +-6743223186536623446246914 = -6743223186536623446251414 bor 6558. +-6743223186536623446248972 = -6743223186536623446251414 bxor 6558. +6743223186536623446251413 = bnot(-6743223186536623446251414). +-93581021 = -6743223186536623446251414 bsl -56. +-485900438882598815873542327663439070101504 = -6743223186536623446251414 bsr -56. +276366 = -7313 + 283679. +-290992 = -7313 - 283679. +-2074544527 = -7313 * 283679. +7313 = -(-7313). +-7313 = +(-7313). +0 = -7313 div 283679. +-7313 = -7313 rem 283679. +278543 = -7313 band 283679. +-2177 = -7313 bor 283679. +-280720 = -7313 bxor 283679. +7312 = bnot(-7313). +-2853668393557606398511702567684678149242437277163616753279126855717542940748618247492474816462914598136476793411355829154301380767829403805612507136 = -7313 bsl 477. +-1 = -7313 bsr 477. +-639444299611848222499 = -3155 + -639444299611848219344. +639444299611848216189 = -3155 - -639444299611848219344. +2017446765275381132030320 = -3155 * -639444299611848219344. +3155 = -(-3155). +-3155 = +(-3155). +0 = -3155 div -639444299611848219344. +-3155 = -3155 rem -639444299611848219344. +-639444299611848220384 = -3155 band -639444299611848219344. +-2115 = -3155 bor -639444299611848219344. +639444299611848218269 = -3155 bxor -639444299611848219344. +3154 = bnot(-3155). +-25240 = -3155 bsl 3. +-395 = -3155 bsr 3. +-36455956348806219 = -36455956348738666 + -67553. +-36455956348671113 = -36455956348738666 - -67553. +2462709219226343104298 = -36455956348738666 * -67553. +36455956348738666 = -(-36455956348738666). +-36455956348738666 = +(-36455956348738666). +539664505628 = -36455956348738666 div -67553. +-50382 = -36455956348738666 rem -67553. +-36455956348739562 = -36455956348738666 band -67553. +-66657 = -36455956348738666 bor -67553. +36455956348672905 = -36455956348738666 bxor -67553. +36455956348738665 = bnot(-36455956348738666). +-328366062855229048242919725596672 = -36455956348738666 bsl 53. +-5 = -36455956348738666 bsr 53. +-679412090374 = -679451664999 + 39574625. +-679491239624 = -679451664999 - 39574625. +-26889044847961050375 = -679451664999 * 39574625. +679451664999 = -(-679451664999). +-679451664999 = +(-679451664999). +-17168 = -679451664999 div 39574625. +-34502999 = -679451664999 rem 39574625. +154625 = -679451664999 band 39574625. +-679412244999 = -679451664999 bor 39574625. +-679412399624 = -679451664999 bxor 39574625. +679451664998 = bnot(-679451664999). +-155670007609233581977874185118449598377546383149890798288746270941756522693250308637177806401228008507407190240376022799438910969536738155724260046465671742417127808182973484591722793433869805526063007222467423793961010534599949406815404079106073067451699148357632 = -679451664999 bsl 835. +-1 = -679451664999 bsr 835. +-31223276117594453328647389 = -8 + -31223276117594453328647381. +31223276117594453328647373 = -8 - -31223276117594453328647381. +249786208940755626629179048 = -8 * -31223276117594453328647381. +8 = -(-8). +-8 = +(-8). +0 = -8 div -31223276117594453328647381. +-8 = -8 rem -31223276117594453328647381. +-31223276117594453328647384 = -8 band -31223276117594453328647381. +-5 = -8 bor -31223276117594453328647381. +31223276117594453328647379 = -8 bxor -31223276117594453328647381. +7 = bnot(-8). +-645562469521727147413979793000752968582426448207305878207664839135161905504210298657411338320034457858975792993186873344 = -8 bsl 395. +-1 = -8 bsr 395. +-7822355794946638 = 6175 + -7822355794952813. +7822355794958988 = 6175 - -7822355794952813. +-48303047033833620275 = 6175 * -7822355794952813. +-6175 = -(6175). +6175 = +(6175). +0 = 6175 div -7822355794952813. +6175 = 6175 rem -7822355794952813. +6163 = 6175 band -7822355794952813. +-7822355794952801 = 6175 bor -7822355794952813. +-7822355794958964 = 6175 bxor -7822355794952813. +-6176 = bnot(6175). +15288559485174446395004184166400 = 6175 bsl 91. +0 = 6175 bsr 91. +-64646795518781450802 = -27267 + -64646795518781423535. +64646795518781396268 = -27267 - -64646795518781423535. +1762724173410613075528845 = -27267 * -64646795518781423535. +27267 = -(-27267). +-27267 = +(-27267). +0 = -27267 div -64646795518781423535. +-27267 = -27267 rem -64646795518781423535. +-64646795518781423535 = -27267 band -64646795518781423535. +-27267 = -27267 bor -64646795518781423535. +64646795518781396268 = -27267 bxor -64646795518781423535. +27266 = bnot(-27267). +-4219363881399307994459302526976 = -27267 bsl 87. +-1 = -27267 bsr 87. +436976517494451682725159518 = 51571916895 + 436976517494451631153242623. +-436976517494451579581325728 = 51571916895 - 436976517494451631153242623. +22535716645290373145432221563127815585 = 51571916895 * 436976517494451631153242623. +-51571916895 = -(51571916895). +51571916895 = +(51571916895). +0 = 51571916895 div 436976517494451631153242623. +51571916895 = 51571916895 rem 436976517494451631153242623. +34366292063 = 51571916895 band 436976517494451631153242623. +436976517494451648358867455 = 51571916895 bor 436976517494451631153242623. +436976517494451613992575392 = 51571916895 bxor 436976517494451631153242623. +-51571916896 = bnot(51571916895). +6601205362560 = 51571916895 bsl 7. +402905600 = 51571916895 bsr 7. +-912671397920102774968391 = 3249731726658748667948 + -915921129646761523636339. +919170861373420272304287 = 3249731726658748667948 - -915921129646761523636339. +-2976497954130201920617341300258571233417362372 = 3249731726658748667948 * -915921129646761523636339. +-3249731726658748667948 = -(3249731726658748667948). +3249731726658748667948 = +(3249731726658748667948). +0 = 3249731726658748667948 div -915921129646761523636339. +3249731726658748667948 = 3249731726658748667948 rem -915921129646761523636339. +562967133327372 = 3249731726658748667948 band -915921129646761523636339. +-912671398483069908295763 = 3249731726658748667948 bor -915921129646761523636339. +-912671399046037041623135 = 3249731726658748667948 bxor -915921129646761523636339. +-3249731726658748667949 = bnot(3249731726658748667948). +11 = 3249731726658748667948 bsl -68. +959151511518210887716537591521349612863488 = 3249731726658748667948 bsr -68. +-62758589555098529255606427693 = -26295371273478989759811 + -62758563259727255776616667882. +62758536964355982297626908071 = -26295371273478989759811 - -62758563259727255776616667882. +1650259721504646028505429441211136333805018338090302 = -26295371273478989759811 * -62758563259727255776616667882. +26295371273478989759811 = -(-26295371273478989759811). +-26295371273478989759811 = +(-26295371273478989759811). +0 = -26295371273478989759811 div -62758563259727255776616667882. +-26295371273478989759811 = -26295371273478989759811 rem -62758563259727255776616667882. +-62758586872718261130464813036 = -26295371273478989759811 band -62758563259727255776616667882. +-2682380268125141614657 = -26295371273478989759811 bor -62758563259727255776616667882. +62758584190337993005323198379 = -26295371273478989759811 bxor -62758563259727255776616667882. +26295371273478989759810 = bnot(-26295371273478989759811). +-841451880751327672313952 = -26295371273478989759811 bsl 5. +-821730352296218429995 = -26295371273478989759811 bsr 5. +-23513526692704330458733 = -23513526661191814622388 + -31512515836345. +-23513526629679298786043 = -23513526661191814622388 - -31512515836345. +740970381279127431619689386181091860 = -23513526661191814622388 * -31512515836345. +23513526661191814622388 = -(-23513526661191814622388). +-23513526661191814622388 = +(-23513526661191814622388). +746164691 = -23513526661191814622388 div -31512515836345. +-19532841127993 = -23513526661191814622388 rem -31512515836345. +-23513526679471195684284 = -23513526661191814622388 band -31512515836345. +-13233134774449 = -23513526661191814622388 bor -31512515836345. +23513526666238060909835 = -23513526661191814622388 bxor -31512515836345. +23513526661191814622387 = bnot(-23513526661191814622388). +-1298275173872345034147165274034282455511155004697235724928149296177900551399900966119521910784 = -23513526661191814622388 bsl 235. +-1 = -23513526661191814622388 bsr 235. +9482913998 = 3 + 9482913995. +-9482913992 = 3 - 9482913995. +28448741985 = 3 * 9482913995. +-3 = -(3). +3 = +(3). +0 = 3 div 9482913995. +3 = 3 rem 9482913995. +3 = 3 band 9482913995. +9482913995 = 3 bor 9482913995. +9482913992 = 3 bxor 9482913995. +-4 = bnot(3). +96 = 3 bsl 5. +0 = 3 bsr 5. +-55166011823650092204876573962 = 647941623139971541625682 + -55166659765273232176418199644. +55167307706896372147959825326 = 647941623139971541625682 - -55166659765273232176418199644. +-35744775071521699508529009213111107931222023393657208 = 647941623139971541625682 * -55166659765273232176418199644. +-647941623139971541625682 = -(647941623139971541625682). +647941623139971541625682 = +(647941623139971541625682). +0 = 647941623139971541625682 div -55166659765273232176418199644. +647941623139971541625682 = 647941623139971541625682 rem -55166659765273232176418199644. +5398843323464184029952 = 647941623139971541625682 band -55166659765273232176418199644. +-55166017222493415669060603914 = 647941623139971541625682 bor -55166659765273232176418199644. +-55166022621336739133244633866 = 647941623139971541625682 bxor -55166659765273232176418199644. +-647941623139971541625683 = bnot(647941623139971541625682). +3059817803972356533925082117027148782131740672 = 647941623139971541625682 bsl 72. +137 = 647941623139971541625682 bsr 72. +-94676213915211394031 = -94676213915211394576 + 545. +-94676213915211395121 = -94676213915211394576 - 545. +-51598536583790210043920 = -94676213915211394576 * 545. +94676213915211394576 = -(-94676213915211394576). +-94676213915211394576 = +(-94676213915211394576). +-173717823697635586 = -94676213915211394576 div 545. +-206 = -94676213915211394576 rem 545. +32 = -94676213915211394576 band 545. +-94676213915211394063 = -94676213915211394576 bor 545. +-94676213915211394095 = -94676213915211394576 bxor 545. +94676213915211394575 = bnot(-94676213915211394576). +-24237110762294117011456 = -94676213915211394576 bsl 8. +-369828960606294511 = -94676213915211394576 bsr 8. +8476635749175533995 = -421 + 8476635749175534416. +-8476635749175534837 = -421 - 8476635749175534416. +-3568663650402899989136 = -421 * 8476635749175534416. +421 = -(-421). +-421 = +(-421). +0 = -421 div 8476635749175534416. +-421 = -421 rem 8476635749175534416. +8476635749175534160 = -421 band 8476635749175534416. +-165 = -421 bor 8476635749175534416. +-8476635749175534325 = -421 bxor 8476635749175534416. +420 = bnot(-421). +-1 = -421 bsl -45. +-14812620649398272 = -421 bsr -45. +217959599599587342411256227 = 593 + 217959599599587342411255634. +-217959599599587342411255041 = 593 - 217959599599587342411255634. +129250042562555294049874590962 = 593 * 217959599599587342411255634. +-593 = -(593). +593 = +(593). +0 = 593 div 217959599599587342411255634. +593 = 593 rem 217959599599587342411255634. +592 = 593 band 217959599599587342411255634. +217959599599587342411255635 = 593 bor 217959599599587342411255634. +217959599599587342411255043 = 593 bxor 217959599599587342411255634. +-594 = bnot(593). +151808 = 593 bsl 8. +2 = 593 bsr 8. +79988115792698 = -563244 + 79988116355942. +-79988116919186 = -563244 - 79988116355942. +-45052826608786195848 = -563244 * 79988116355942. +563244 = -(-563244). +-563244 = +(-563244). +0 = -563244 div 79988116355942. +-563244 = -563244 rem 79988116355942. +79988116316996 = -563244 band 79988116355942. +-524298 = -563244 bor 79988116355942. +-79988116841294 = -563244 bxor 79988116355942. +563243 = bnot(-563244). +-1 = -563244 bsl -863. +-34640394721061065329294333911444814820087240462411338301543274614380197084003586409358386052212163938506038968169842635468627438974162867844936272174280595390147919468853578393758858430914247218108454374614230194304365670276172533634851456485821480532627746981937152 = -563244 bsr -863. +-8556525880857951556791276 = 726465657566678 + -8556525881584417214357954. +8556525882310882871924632 = 726465657566678 - -8556525881584417214357954. +-6216022201051522826115155263983714656812 = 726465657566678 * -8556525881584417214357954. +-726465657566678 = -(726465657566678). +726465657566678 = +(726465657566678). +0 = 726465657566678 div -8556525881584417214357954. +726465657566678 = 726465657566678 rem -8556525881584417214357954. +21996143711254 = 726465657566678 band -8556525881584417214357954. +-8556525880879947700502530 = 726465657566678 bor -8556525881584417214357954. +-8556525880901943844213784 = 726465657566678 bxor -8556525881584417214357954. +-726465657566679 = bnot(726465657566678). +185975208337069568 = 726465657566678 bsl 8. +2837756474869 = 726465657566678 bsr 8. +9789649 = -28126 + 9817775. +-9845901 = -28126 - 9817775. +-276134739650 = -28126 * 9817775. +28126 = -(-28126). +-28126 = +(-28126). +0 = -28126 div 9817775. +-28126 = -28126 rem 9817775. +9798178 = -28126 band 9817775. +-8529 = -28126 bor 9817775. +-9806707 = -28126 bxor 9817775. +28125 = bnot(-28126). +-1 = -28126 bsl -64. +-518833123817154848751616 = -28126 bsr -64. +63316455963147 = 9 + 63316455963138. +-63316455963129 = 9 - 63316455963138. +569848103668242 = 9 * 63316455963138. +-9 = -(9). +9 = +(9). +0 = 9 div 63316455963138. +9 = 9 rem 63316455963138. +0 = 9 band 63316455963138. +63316455963147 = 9 bor 63316455963138. +63316455963147 = 9 bxor 63316455963138. +-10 = bnot(9). +144 = 9 bsl 4. +0 = 9 bsr 4. +7296844515889252715100 = 7296838576556419786673 + 5939332832928427. +7296832637223586858246 = 7296838576556419786673 - 5939332832928427. +43338352934320271488477932101217453371 = 7296838576556419786673 * 5939332832928427. +-7296838576556419786673 = -(7296838576556419786673). +7296838576556419786673 = +(7296838576556419786673). +1228561 = 7296838576556419786673 div 5939332832928427. +5892001038583126 = 7296838576556419786673 rem 5939332832928427. +4531096076493473 = 7296838576556419786673 band 5939332832928427. +7296839984793176221627 = 7296838576556419786673 bor 5939332832928427. +7296835453697099728154 = 7296838576556419786673 bxor 5939332832928427. +-7296838576556419786674 = bnot(7296838576556419786673). +0 = 7296838576556419786673 bsl -532. +102587024151951932244548571765698531258935873397019643020672834543681182372243810323536922545540017678616196319719868675345631069947330350527532819302325602914141803302531159931486208 = 7296838576556419786673 bsr -532. +-91245673612382390408697634 = -91245673612417952937469295 + 35562528771661. +-91245673612453515466240956 = -91245673612417952937469295 - 35562528771661. +-3244926893131202344473484034258253648995 = -91245673612417952937469295 * 35562528771661. +91245673612417952937469295 = -(-91245673612417952937469295). +-91245673612417952937469295 = +(-91245673612417952937469295). +-2565781364938 = -91245673612417952937469295 div 35562528771661. +-18695824047277 = -91245673612417952937469295 rem 35562528771661. +378108185089 = -91245673612417952937469295 band 35562528771661. +-91245673612382768516882723 = -91245673612417952937469295 bor 35562528771661. +-91245673612383146625067812 = -91245673612417952937469295 bxor 35562528771661. +91245673612417952937469294 = bnot(-91245673612417952937469295). +-1 = -91245673612417952937469295 bsl -686. +-29294717018410934065107356110468495676928046273552651572128166411163755894770684486824260955216737260266573314290990495657167626170151376088394384892210106258096923019338891602242482231931183866946163680066951951064290274210354298880 = -91245673612417952937469295 bsr -686. +-9199662011147518 = -9283927165491291 + 84265154343773. +-9368192319835064 = -9283927165491291 - 84265154343773. +-782311555516470615236251580943 = -9283927165491291 * 84265154343773. +9283927165491291 = -(-9283927165491291). +-9283927165491291 = +(-9283927165491291). +-110 = -9283927165491291 div 84265154343773. +-14760187676261 = -9283927165491291 rem 84265154343773. +4402375435013 = -9283927165491291 band 84265154343773. +-9204064386582531 = -9283927165491291 bor 84265154343773. +-9208466762017544 = -9283927165491291 bxor 84265154343773. +9283927165491290 = bnot(-9283927165491291). +-74271417323930328 = -9283927165491291 bsl 3. +-1160490895686412 = -9283927165491291 bsr 3. +6122188 = -584 + 6122772. +-6123356 = -584 - 6122772. +-3575698848 = -584 * 6122772. +584 = -(-584). +-584 = +(-584). +0 = -584 div 6122772. +-584 = -584 rem 6122772. +6122768 = -584 band 6122772. +-580 = -584 bor 6122772. +-6123348 = -584 bxor 6122772. +583 = bnot(-584). +-40656514292775909541113955958999178066065146610003036490756964576006724512479669093619584378194349631816514721542040006552767998615772335677788607951626176238085401761267009442877174808838144 = -584 bsl 624. +-1 = -584 bsr 624. +53933372059795890975 = 37215668448636 + 53933334844127442339. +-53933297628458993703 = 37215668448636 - 53933334844127442339. +2007165107888314254907326673199604 = 37215668448636 * 53933334844127442339. +-37215668448636 = -(37215668448636). +37215668448636 = +(37215668448636). +0 = 37215668448636 div 53933334844127442339. +37215668448636 = 37215668448636 rem 53933334844127442339. +35494148744480 = 37215668448636 band 53933334844127442339. +53933336565647146495 = 37215668448636 bor 53933334844127442339. +53933301071498402015 = 37215668448636 bxor 53933334844127442339. +-37215668448637 = bnot(37215668448636). +595450695178176 = 37215668448636 bsl 4. +2325979278039 = 37215668448636 bsr 4. +9566197812430892 = 9534647661 + 9566188277783231. +-9566178743135570 = 9534647661 - 9566188277783231. +91210234687451501719172691 = 9534647661 * 9566188277783231. +-9534647661 = -(9534647661). +9534647661 = +(9534647661). +0 = 9534647661 div 9566188277783231. +9534647661 = 9534647661 rem 9566188277783231. +395309 = 9534647661 band 9566188277783231. +9566197812035583 = 9534647661 bor 9566188277783231. +9566197811640274 = 9534647661 bxor 9566188277783231. +-9534647662 = bnot(9534647661). +0 = 9534647661 bsl -793. +496696626687282375377939935965836735613470956377184826911039002953819968230271768556956314417265994372395239252551698187320658279355797931861652732925518299196794659366716565832577633856476303462101737891022331623015356684381760015565255495240384512 = 9534647661 bsr -793. +938397723693288956 = 938397723693288917 + 39. +938397723693288878 = 938397723693288917 - 39. +36597511224038267763 = 938397723693288917 * 39. +-938397723693288917 = -(938397723693288917). +938397723693288917 = +(938397723693288917). +24061480094699715 = 938397723693288917 div 39. +32 = 938397723693288917 rem 39. +5 = 938397723693288917 band 39. +938397723693288951 = 938397723693288917 bor 39. +938397723693288946 = 938397723693288917 bxor 39. +-938397723693288918 = bnot(938397723693288917). +58649857730830557 = 938397723693288917 bsl -4. +15014363579092622672 = 938397723693288917 bsr -4. +43959977489574816370 = -9768 + 43959977489574826138. +-43959977489574835906 = -9768 - 43959977489574826138. +-429401060118166901715984 = -9768 * 43959977489574826138. +9768 = -(-9768). +-9768 = +(-9768). +0 = -9768 div 43959977489574826138. +-9768 = -9768 rem 43959977489574826138. +43959977489574826136 = -9768 band 43959977489574826138. +-9766 = -9768 bor 43959977489574826138. +-43959977489574835902 = -9768 bxor 43959977489574826138. +9767 = bnot(-9768). +-1 = -9768 bsl -94. +-193475172859833512403434326720512 = -9768 bsr -94. +2962685 = 2962587 + 98. +2962489 = 2962587 - 98. +290333526 = 2962587 * 98. +-2962587 = -(2962587). +2962587 = +(2962587). +30230 = 2962587 div 98. +47 = 2962587 rem 98. +2 = 2962587 band 98. +2962683 = 2962587 bor 98. +2962681 = 2962587 bxor 98. +-2962588 = bnot(2962587). +46290 = 2962587 bsl -6. +189605568 = 2962587 bsr -6. +-889113815585846537540801435783 = -889113815585846533226317722798 + -4314483712985. +-889113815585846528911834009813 = -889113815585846533226317722798 - -4314483712985. +3836067076335083713688673459976825023132030 = -889113815585846533226317722798 * -4314483712985. +889113815585846533226317722798 = -(-889113815585846533226317722798). +-889113815585846533226317722798 = +(-889113815585846533226317722798). +206076526122915435 = -889113815585846533226317722798 div -4314483712985. +-734351299323 = -889113815585846533226317722798 rem -4314483712985. +-889113815585846533930864343038 = -889113815585846533226317722798 band -4314483712985. +-3609937092745 = -889113815585846533226317722798 bor -4314483712985. +889113815585846530320927250293 = -889113815585846533226317722798 bxor -4314483712985. +889113815585846533226317722797 = bnot(-889113815585846533226317722798). +-1791816582989376561490997744830221417691895980460967584164720991418785143992020564566076037250058614790535884958141103004067848722060363009988868482825768479955320716208227978961243998689015388323903187582743175153472415090077713829853735621254211466096507757345074364569772653221305600664666112 = -889113815585846533226317722798 bsl 878. +-1 = -889113815585846533226317722798 bsr 878. +-28463619149739495954188715 = -28463619149739495954188711 + -4. +-28463619149739495954188707 = -28463619149739495954188711 - -4. +113854476598957983816754844 = -28463619149739495954188711 * -4. +28463619149739495954188711 = -(-28463619149739495954188711). +-28463619149739495954188711 = +(-28463619149739495954188711). +7115904787434873988547177 = -28463619149739495954188711 div -4. +-3 = -28463619149739495954188711 rem -4. +-28463619149739495954188712 = -28463619149739495954188711 band -4. +-3 = -28463619149739495954188711 bor -4. +28463619149739495954188709 = -28463619149739495954188711 bxor -4. +28463619149739495954188710 = bnot(-28463619149739495954188711). +-53017622138819650 = -28463619149739495954188711 bsl -29. +-15281289171741307755345603494674432 = -28463619149739495954188711 bsr -29. +-39144435271099 = -39144434357238 + -913861. +-39144433443377 = -39144434357238 - -913861. +35772571926139875918 = -39144434357238 * -913861. +39144434357238 = -(-39144434357238). +-39144434357238 = +(-39144434357238). +42834122 = -39144434357238 div -913861. +-792196 = -39144434357238 rem -913861. +-39144434693110 = -39144434357238 band -913861. +-577989 = -39144434357238 bor -913861. +39144434115121 = -39144434357238 bxor -913861. +39144434357237 = bnot(-39144434357238). +-156577737428952 = -39144434357238 bsl 2. +-9786108589310 = -39144434357238 bsr 2. +-2267949984571668733125 = -2267949984568444421677 + -3224311448. +-2267949984565220110229 = -2267949984568444421677 - -3224311448. +7312577098735458688364890458296 = -2267949984568444421677 * -3224311448. +2267949984568444421677 = -(-2267949984568444421677). +-2267949984568444421677 = +(-2267949984568444421677). +703390482323 = -2267949984568444421677 div -3224311448. +-153887973 = -2267949984568444421677 rem -3224311448. +-2267949984568447047360 = -2267949984568444421677 band -3224311448. +-3221685765 = -2267949984568444421677 bor -3224311448. +2267949984565225361595 = -2267949984568444421677 bxor -3224311448. +2267949984568444421676 = bnot(-2267949984568444421677). +-4429589813610243012 = -2267949984568444421677 bsl -9. +-1161190392099043543898624 = -2267949984568444421677 bsr -9. +-24642187589952063846 = -917727727296215997 + -23724459862655847849. +22806732135359631852 = -917727727296215997 - -23724459862655847849. +21772594631085447961223694261471840453 = -917727727296215997 * -23724459862655847849. +917727727296215997 = -(-917727727296215997). +-917727727296215997 = +(-917727727296215997). +0 = -917727727296215997 div -23724459862655847849. +-917727727296215997 = -917727727296215997 rem -23724459862655847849. +-24048798206334435261 = -917727727296215997 band -23724459862655847849. +-593389383617628585 = -917727727296215997 bor -23724459862655847849. +23455408822716806676 = -917727727296215997 bxor -23724459862655847849. +917727727296215996 = bnot(-917727727296215997). +-3584873934750844 = -917727727296215997 bsl -8. +-234938298187831295232 = -917727727296215997 bsr -8. +68879551139130795 = 68879551138896923 + 233872. +68879551138663051 = 68879551138896923 - 233872. +16108998383956101175856 = 68879551138896923 * 233872. +-68879551138896923 = -(68879551138896923). +68879551138896923 = +(68879551138896923). +294518160099 = 68879551138896923 div 233872. +223595 = 68879551138896923 rem 233872. +4112 = 68879551138896923 band 233872. +68879551139126683 = 68879551138896923 bor 233872. +68879551139122571 = 68879551138896923 bxor 233872. +-68879551138896924 = bnot(68879551138896923). +8816582545778806144 = 68879551138896923 bsl 7. +538121493272632 = 68879551138896923 bsr 7. +-524372124561571424235676612096 = 6114152 + -524372124561571424235682726248. +524372124561571424235688840400 = 6114152 - -524372124561571424235682726248. +-3206090874132381046633448012054661696 = 6114152 * -524372124561571424235682726248. +-6114152 = -(6114152). +6114152 = +(6114152). +0 = 6114152 div -524372124561571424235682726248. +6114152 = 6114152 rem -524372124561571424235682726248. +5261832 = 6114152 band -524372124561571424235682726248. +-524372124561571424235681873928 = 6114152 bor -524372124561571424235682726248. +-524372124561571424235687135760 = 6114152 bxor -524372124561571424235682726248. +-6114153 = bnot(6114152). +0 = 6114152 bsl -77. +923944527231053024723514425344 = 6114152 bsr -77. +9493229794381587 = -2 + 9493229794381589. +-9493229794381591 = -2 - 9493229794381589. +-18986459588763178 = -2 * 9493229794381589. +2 = -(-2). +-2 = +(-2). +0 = -2 div 9493229794381589. +-2 = -2 rem 9493229794381589. +9493229794381588 = -2 band 9493229794381589. +-1 = -2 bor 9493229794381589. +-9493229794381589 = -2 bxor 9493229794381589. +1 = bnot(-2). +-562949953421312 = -2 bsl 48. +-1 = -2 bsr 48. +338654 = 337727 + 927. +336800 = 337727 - 927. +313072929 = 337727 * 927. +-337727 = -(337727). +337727 = +(337727). +364 = 337727 div 927. +299 = 337727 rem 927. +799 = 337727 band 927. +337855 = 337727 bor 927. +337056 = 337727 bxor 927. +-337728 = bnot(337727). +0 = 337727 bsl -588. +342139512825066188696171867817584175304682721844858761456258145259871851083995905654085415654237920686906788977435249420947941207823631015480153949487501614780300719462251368873459712 = 337727 bsr -588. +39138662259334119678064 = -322563763953267 + 39138662581897883631331. +-39138662904461647584598 = -322563763953267 - 39138662581897883631331. +-12624714318513872489316281894141008377 = -322563763953267 * 39138662581897883631331. +322563763953267 = -(-322563763953267). +-322563763953267 = +(-322563763953267). +0 = -322563763953267 div 39138662581897883631331. +-322563763953267 = -322563763953267 rem 39138662581897883631331. +39138662260743179346049 = -322563763953267 band 39138662581897883631331. +-1409059667985 = -322563763953267 bor 39138662581897883631331. +-39138662262152239014034 = -322563763953267 bxor 39138662581897883631331. +322563763953266 = bnot(-322563763953267). +-181587255892894736365129826304 = -322563763953267 bsl 49. +-1 = -322563763953267 bsr 49. +-6288977272882750121716142727 = 2621979282859 + -6288977272882752743695425586. +6288977272882755365674708445 = 2621979282859 - -6288977272882752743695425586. +-16489568119869669586504346611499079830374 = 2621979282859 * -6288977272882752743695425586. +-2621979282859 = -(2621979282859). +2621979282859 = +(2621979282859). +0 = 2621979282859 div -6288977272882752743695425586. +2621979282859 = 2621979282859 rem -6288977272882752743695425586. +285349006730 = 2621979282859 band -6288977272882752743695425586. +-6288977272882750407065149457 = 2621979282859 bor -6288977272882752743695425586. +-6288977272882750692414156187 = 2621979282859 bxor -6288977272882752743695425586. +-2621979282860 = bnot(2621979282859). +45633792032927766636558829632437146623729424500201394081270271387439117523627148615542082354664238135683294503022951256421709887736295998881361127556508864099138488079282435334867583874528003946971136 = 2621979282859 bsl 622. +0 = 2621979282859 bsr 622. +-981608 = -95 + -981513. +981418 = -95 - -981513. +93243735 = -95 * -981513. +95 = -(-95). +-95 = +(-95). +0 = -95 div -981513. +-95 = -95 rem -981513. +-981599 = -95 band -981513. +-9 = -95 bor -981513. +981590 = -95 bxor -981513. +94 = bnot(-95). +-3040 = -95 bsl 5. +-3 = -95 bsr 5. +-72159589933345004080192207563 = -25565764779621271 + -72159589933319438315412586292. +72159589933293872550632965021 = -25565764779621271 - -72159589933319438315412586292. +1844815102829171715237701492238966502366217132 = -25565764779621271 * -72159589933319438315412586292. +25565764779621271 = -(-25565764779621271). +-25565764779621271 = +(-25565764779621271). +0 = -25565764779621271 div -72159589933319438315412586292. +-25565764779621271 = -25565764779621271 rem -72159589933319438315412586292. +-72159589933344228730818396088 = -25565764779621271 band -72159589933319438315412586292. +-775349373811475 = -25565764779621271 bor -72159589933319438315412586292. +72159589933343453381444584613 = -25565764779621271 bxor -72159589933319438315412586292. +25565764779621270 = bnot(-25565764779621271). +-1 = -25565764779621271 bsl -552. +-376891545469205666692423721188611135467462423258473339765083709194668716109829979210087156306882816693633085329973128696206684696862091342922014883525884084455336719448376222119100416 = -25565764779621271 bsr -552. +853762466 = 4 + 853762462. +-853762458 = 4 - 853762462. +3415049848 = 4 * 853762462. +-4 = -(4). +4 = +(4). +0 = 4 div 853762462. +4 = 4 rem 853762462. +4 = 4 band 853762462. +853762462 = 4 bor 853762462. +853762458 = 4 bxor 853762462. +-5 = bnot(4). +0 = 4 bsl -3. +32 = 4 bsr -3. +1423394379825560705171 = 583911822985914123515 + 839482556839646581656. +-255570733853732458141 = 583911822985914123515 - 839482556839646581656. +490183790129114306563518065187741117240840 = 583911822985914123515 * 839482556839646581656. +-583911822985914123515 = -(583911822985914123515). +583911822985914123515 = +(583911822985914123515). +0 = 583911822985914123515 div 839482556839646581656. +583911822985914123515 = 583911822985914123515 rem 839482556839646581656. +249184450009142952088 = 583911822985914123515 band 839482556839646581656. +1174209929816417753083 = 583911822985914123515 bor 839482556839646581656. +925025479807274800995 = 583911822985914123515 bxor 839482556839646581656. +-583911822985914123516 = bnot(583911822985914123515). +0 = 583911822985914123515 bsl -489. +933286854102346590916038334878114268698088764671016388629042772055499685121238063867877641091156694537038817124889329230541736781305155973928074893116930143895085383680 = 583911822985914123515 bsr -489. +-95896673865189 = -96592446293331 + 695772428142. +-97288218721473 = -96592446293331 - 695772428142. +-67206360897686637451321002 = -96592446293331 * 695772428142. +96592446293331 = -(-96592446293331). +-96592446293331 = +(-96592446293331). +-138 = -96592446293331 div 695772428142. +-575851209735 = -96592446293331 rem 695772428142. +138798215724 = -96592446293331 band 695772428142. +-96035472080913 = -96592446293331 bor 695772428142. +-96174270296637 = -96592446293331 bxor 695772428142. +96592446293330 = bnot(-96592446293331). +-1 = -96592446293331 bsl -221. +-325515900064727033006723633047949897409224347669638580099791894982130765043597312 = -96592446293331 bsr -221. +-7289159845218643776343174512 = -7289159845218643776343173517 + -995. +-7289159845218643776343172522 = -7289159845218643776343173517 - -995. +7252714045992550557461457649415 = -7289159845218643776343173517 * -995. +7289159845218643776343173517 = -(-7289159845218643776343173517). +-7289159845218643776343173517 = +(-7289159845218643776343173517). +7325788789164466106877561 = -7289159845218643776343173517 div -995. +-322 = -7289159845218643776343173517 rem -995. +-7289159845218643776343174127 = -7289159845218643776343173517 band -995. +-385 = -7289159845218643776343173517 bor -995. +7289159845218643776343173742 = -7289159845218643776343173517 bxor -995. +7289159845218643776343173516 = bnot(-7289159845218643776343173517). +-70496428321463939690824451884876015117562414876327936 = -7289159845218643776343173517 bsl 83. +-754 = -7289159845218643776343173517 bsr 83. +35376388787642844912187156 = 593 + 35376388787642844912186563. +-35376388787642844912185970 = 593 - 35376388787642844912186563. +20978198551072207032926631859 = 593 * 35376388787642844912186563. +-593 = -(593). +593 = +(593). +0 = 593 div 35376388787642844912186563. +593 = 593 rem 35376388787642844912186563. +65 = 593 band 35376388787642844912186563. +35376388787642844912187091 = 593 bor 35376388787642844912186563. +35376388787642844912187026 = 593 bxor 35376388787642844912186563. +-594 = bnot(593). +0 = 593 bsl -35. +20375324852224 = 593 bsr -35. +-88383936180025438134421 = -88383944478485252746958 + 8298459814612537. +-88383952776945067359495 = -88383944478485252746958 - 8298459814612537. +-733450611511655493711281995007675412446 = -88383944478485252746958 * 8298459814612537. +88383944478485252746958 = -(-88383944478485252746958). +-88383944478485252746958 = +(-88383944478485252746958). +-10650644 = -88383944478485252746958 div 8298459814612537. +-3244741123223130 = -88383944478485252746958 rem 8298459814612537. +8289244542320688 = -88383944478485252746958 band 8298459814612537. +-88383944469269980455109 = -88383944478485252746958 bor 8298459814612537. +-88383952758514522775797 = -88383944478485252746958 bxor 8298459814612537. +88383944478485252746957 = bnot(-88383944478485252746958). +-1 = -88383944478485252746958 bsl -498. +-72328793436171923303501242904921538868908174232957948869553245322491821288425462681446794260789939913028086656509573167011669502730599213013225742326068691415924548464279552 = -88383944478485252746958 bsr -498. +-432 = -516 + 84. +-600 = -516 - 84. +-43344 = -516 * 84. +516 = -(-516). +-516 = +(-516). +-6 = -516 div 84. +-12 = -516 rem 84. +84 = -516 band 84. +-516 = -516 bor 84. +-600 = -516 bxor 84. +515 = bnot(-516). +-129 = -516 bsl -2. +-2064 = -516 bsr -2. +-5596641981436881743594547168 = -5596641981436935356756388516 + 53613161841348. +-5596641981436988969918229864 = -5596641981436935356756388516 - 53613161841348. +-300053672318860964426375383823133041159568 = -5596641981436935356756388516 * 53613161841348. +5596641981436935356756388516 = -(-5596641981436935356756388516). +-5596641981436935356756388516 = +(-5596641981436935356756388516). +-104389328836797 = -5596641981436935356756388516 div 53613161841348. +-42033257906160 = -5596641981436935356756388516 rem 53613161841348. +17868295372868 = -5596641981436935356756388516 band 53613161841348. +-5596641981436899611889920036 = -5596641981436935356756388516 bor 53613161841348. +-5596641981436917480185292904 = -5596641981436935356756388516 bxor 53613161841348. +5596641981436935356756388515 = bnot(-5596641981436935356756388516). +-1289155062446397240207348514759687647736457136729469815900398414886254960824036212425282575915046285725246915330099303076472005333399133729486620438473826088340577967551488726816896503852826624 = -5596641981436935356756388516 bsl 546. +-1 = -5596641981436935356756388516 bsr 546. +284396196340718960184592278332 = -217734169182222469124 + 284396196558453129366814747456. +-284396196776187298549037216580 = -217734169182222469124 - 284396196558453129366814747456. +-61922769576238829194488665641522602052528817548544 = -217734169182222469124 * 284396196558453129366814747456. +217734169182222469124 = -(-217734169182222469124). +-217734169182222469124 = +(-217734169182222469124). +0 = -217734169182222469124 div 284396196558453129366814747456. +-217734169182222469124 = -217734169182222469124 rem 284396196558453129366814747456. +284396196489160710023662412608 = -217734169182222469124 band 284396196558453129366814747456. +-148441749839070134276 = -217734169182222469124 bor 284396196558453129366814747456. +-284396196637602459862732546884 = -217734169182222469124 bxor 284396196558453129366814747456. +217734169182222469123 = bnot(-217734169182222469124). +-1 = -217734169182222469124 bsl -439. +-309096925320254733711942867352297104175140757235372806325969408707524208701220561286286948547716279158327238545931855047770537522991128544603004429402112 = -217734169182222469124 bsr -439. +985223770122340129850815 = -3398973293555211497613 + 988622743415895341348428. +-992021716709450552846041 = -3398973293555211497613 - 988622743415895341348428. +-3360302302271914570872637267312734552723302364 = -3398973293555211497613 * 988622743415895341348428. +3398973293555211497613 = -(-3398973293555211497613). +-3398973293555211497613 = +(-3398973293555211497613). +0 = -3398973293555211497613 div 988622743415895341348428. +-3398973293555211497613 = -3398973293555211497613 rem 988622743415895341348428. +988175400125004939593280 = -3398973293555211497613 band 988622743415895341348428. +-2951630002664809742465 = -3398973293555211497613 bor 988622743415895341348428. +-991127030127669749335745 = -3398973293555211497613 bxor 988622743415895341348428. +3398973293555211497612 = bnot(-3398973293555211497613). +-217534290787533535847232 = -3398973293555211497613 bsl 6. +-53108957711800179651 = -3398973293555211497613 bsr 6. +-1048780507735075470499531127922 = -299912126399476783966892396589 + -748868381335598686532638731333. +448956254936121902565746334744 = -299912126399476783966892396589 - -748868381335598686532638731333. +224594708639693654151248600938408959574771763247688856623137 = -299912126399476783966892396589 * -748868381335598686532638731333. +299912126399476783966892396589 = -(-299912126399476783966892396589). +-299912126399476783966892396589 = +(-299912126399476783966892396589). +0 = -299912126399476783966892396589 div -748868381335598686532638731333. +-299912126399476783966892396589 = -299912126399476783966892396589 rem -748868381335598686532638731333. +-949414776692567621220798692461 = -299912126399476783966892396589 band -748868381335598686532638731333. +-99365731042507849278732435461 = -299912126399476783966892396589 bor -748868381335598686532638731333. +850049045650059771942066257000 = -299912126399476783966892396589 bxor -748868381335598686532638731333. +299912126399476783966892396588 = bnot(-299912126399476783966892396589). +-2515845262811662145798945293165658112 = -299912126399476783966892396589 bsl 23. +-35752311515745733257162 = -299912126399476783966892396589 bsr 23. +544613 = -84835 + 629448. +-714283 = -84835 - 629448. +-53399221080 = -84835 * 629448. +84835 = -(-84835). +-84835 = +(-84835). +0 = -84835 div 629448. +-84835 = -84835 rem 629448. +561288 = -84835 band 629448. +-16675 = -84835 bor 629448. +-577963 = -84835 bxor 629448. +84834 = bnot(-84835). +-1 = -84835 bsl -97. +-13442642333795230159496602053509120 = -84835 bsr -97. +-36121523960803135913611 = -36121524847967313194856 + 887164177281245. +-36121525735131490476101 = -36121524847967313194856 - 887164177281245. +-32045722873890969789282230872999275720 = -36121524847967313194856 * 887164177281245. +36121524847967313194856 = -(-36121524847967313194856). +-36121524847967313194856 = +(-36121524847967313194856). +-40715716 = -36121524847967313194856 div 887164177281245. +-160410489648436 = -36121524847967313194856 rem 887164177281245. +3092378554520 = -36121524847967313194856 band 887164177281245. +-36121523963895514468131 = -36121524847967313194856 bor 887164177281245. +-36121523966987893022651 = -36121524847967313194856 bxor 887164177281245. +36121524847967313194855 = bnot(-36121524847967313194856). +-1 = -36121524847967313194856 bsl -555. +-4260039921983946223320372338255047661798517726710739357683710915733751398170472437637779148660565183876332275255098994351650385918924882566819183379734039604666474308285291287373178478788608 = -36121524847967313194856 bsr -555. +-5228933976190874131121760902 = -5228933976191629529339534856 + 755398217773954. +-5228933976192384927557308810 = -5228933976191629529339534856 - 755398217773954. +-3949927406472831763397050258582202111940624 = -5228933976191629529339534856 * 755398217773954. +5228933976191629529339534856 = -(-5228933976191629529339534856). +-5228933976191629529339534856 = +(-5228933976191629529339534856). +-6922089373735 = -5228933976191629529339534856 div 755398217773954. +-185139684836666 = -5228933976191629529339534856 rem 755398217773954. +578372112294272 = -5228933976191629529339534856 band 755398217773954. +-5228933976191452503234055174 = -5228933976191629529339534856 bor 755398217773954. +-5228933976192030875346349446 = -5228933976191629529339534856 bxor 755398217773954. +5228933976191629529339534855 = bnot(-5228933976191629529339534856). +-20915735904766518117358139424 = -5228933976191629529339534856 bsl 2. +-1307233494047907382334883714 = -5228933976191629529339534856 bsr 2. +-2313941712627712635797936 = -58825119 + -2313941712627712576972817. +2313941712627712518147698 = -58825119 - -2313941712627712576972817. +136117896604388995038222619790223 = -58825119 * -2313941712627712576972817. +58825119 = -(-58825119). +-58825119 = +(-58825119). +0 = -58825119 div -2313941712627712576972817. +-58825119 = -58825119 rem -2313941712627712576972817. +-2313941712627712585365919 = -58825119 band -2313941712627712576972817. +-50432017 = -58825119 bor -2313941712627712576972817. +2313941712627712534933902 = -58825119 bxor -2313941712627712576972817. +58825118 = bnot(-58825119). +-459572 = -58825119 bsl -7. +-7529615232 = -58825119 bsr -7. +-39532178545449714486969974045 = -39144824719771556967531838878 + -387353825678157519438135167. +-38757470894093399448093703711 = -39144824719771556967531838878 - -387353825678157519438135167. +15162897610704422948379732234328403070831799486629622626 = -39144824719771556967531838878 * -387353825678157519438135167. +39144824719771556967531838878 = -(-39144824719771556967531838878). +-39144824719771556967531838878 = +(-39144824719771556967531838878). +101 = -39144824719771556967531838878 div -387353825678157519438135167. +-22088326277647504280187011 = -39144824719771556967531838878 rem -387353825678157519438135167. +-39454500041501834731337220096 = -39144824719771556967531838878 band -387353825678157519438135167. +-77678503947879755632753949 = -39144824719771556967531838878 bor -387353825678157519438135167. +39376821537553954975704466147 = -39144824719771556967531838878 bxor -387353825678157519438135167. +39144824719771556967531838877 = bnot(-39144824719771556967531838878). +-36261288297047112456574047448012037405591068471788300549971762926424652906450749839118480673786272849854464 = -39144824719771556967531838878 bsl 259. +-1 = -39144824719771556967531838878 bsr 259. +96442260946113395843907062 = 9714399119165457325774274 + 86727861826947938518132788. +-77013462707782481192358514 = 9714399119165457325774274 - 86727861826947938518132788. +842509064538806544487422868581886775245460846295912 = 9714399119165457325774274 * 86727861826947938518132788. +-9714399119165457325774274 = -(9714399119165457325774274). +9714399119165457325774274 = +(9714399119165457325774274). +0 = 9714399119165457325774274 div 86727861826947938518132788. +9714399119165457325774274 = 9714399119165457325774274 rem 86727861826947938518132788. +42842645781906634850304 = 9714399119165457325774274 band 86727861826947938518132788. +96399418300331489209056758 = 9714399119165457325774274 bor 86727861826947938518132788. +96356575654549582574206454 = 9714399119165457325774274 bxor 86727861826947938518132788. +-9714399119165457325774275 = bnot(9714399119165457325774274). +155430385906647317212388384 = 9714399119165457325774274 bsl 4. +607149944947841082860892 = 9714399119165457325774274 bsr 4. +58725190968083356687400 = -259348471451611166831 + 58984539439534967854231. +-59243887910986579021062 = -259348471451611166831 - 58984539439534967854231. +-15297550142920667545306486335476338230211961 = -259348471451611166831 * 58984539439534967854231. +259348471451611166831 = -(-259348471451611166831). +-259348471451611166831 = +(-259348471451611166831). +0 = -259348471451611166831 div 58984539439534967854231. +-259348471451611166831 = -259348471451611166831 rem 58984539439534967854231. +58762157292493824984209 = -259348471451611166831 band 58984539439534967854231. +-36966324410468296809 = -259348471451611166831 bor 58984539439534967854231. +-58799123616904293281018 = -259348471451611166831 bxor 58984539439534967854231. +259348471451611166830 = bnot(-259348471451611166831). +-11781532008619042716132876004244721666502104356517640457399534631670477333637333442414731753378215776210292300440032904923490970981846667962649607139229696 = -259348471451611166831 bsl 444. +-1 = -259348471451611166831 bsr 444. +591644923315353855980747 = 698822196362898 + 591644922616531659617849. +-591644921917709463254951 = 698822196362898 - 591644922616531659617849. +413454604289841479405363865188402166402 = 698822196362898 * 591644922616531659617849. +-698822196362898 = -(698822196362898). +698822196362898 = +(698822196362898). +0 = 698822196362898 div 591644922616531659617849. +698822196362898 = 698822196362898 rem 591644922616531659617849. +20419084056080 = 698822196362898 band 591644922616531659617849. +591644923294934771924667 = 698822196362898 bor 591644922616531659617849. +591644923274515687868587 = 698822196362898 bxor 591644922616531659617849. +-698822196362899 = bnot(698822196362898). +2795288785451592 = 698822196362898 bsl 2. +174705549090724 = 698822196362898 bsr 2. +-71129950541462559969961 = -6896237721355314 + -71129943645224838614647. +71129936748987117259333 = -6896237721355314 - -71129943645224838614647. +490529000484077238376825442807011684158 = -6896237721355314 * -71129943645224838614647. +6896237721355314 = -(-6896237721355314). +-6896237721355314 = +(-6896237721355314). +0 = -6896237721355314 div -71129943645224838614647. +-6896237721355314 = -6896237721355314 rem -71129943645224838614647. +-71129950400634273123960 = -6896237721355314 band -71129943645224838614647. +-140828286846001 = -6896237721355314 bor -71129943645224838614647. +71129950259805986277959 = -6896237721355314 bxor -71129943645224838614647. +6896237721355313 = bnot(-6896237721355314). +-1 = -6896237721355314 bsl -578. +-6822596977107109636132725784345838907142012186166156789606892117950408498673939962039999041421050078931352102357161071567561607022595870779761007920162403830610258693924129685610207763234816 = -6896237721355314 bsr -578. +-7443127918909037783 = -281491387173284 + -7442846427521864499. +7442564936134691215 = -281491387173284 - -7442846427521864499. +2095097165400850810996268880844716 = -281491387173284 * -7442846427521864499. +281491387173284 = -(-281491387173284). +-281491387173284 = +(-281491387173284). +0 = -281491387173284 div -7442846427521864499. +-281491387173284 = -281491387173284 rem -7442846427521864499. +-7443127917531093940 = -281491387173284 band -7442846427521864499. +-1377943843 = -281491387173284 bor -7442846427521864499. +7443127916153150097 = -281491387173284 bxor -7442846427521864499. +281491387173283 = bnot(-281491387173284). +-72061795116360704 = -281491387173284 bsl 8. +-1099575731146 = -281491387173284 bsr 8. +-771246567331013984771121652752 = -771782222179325333442389628311 + 535654848311348671267975559. +-772317877027636682113657603870 = -771782222179325333442389628311 - 535654848311348671267975559. +-413408889150862109611410971768391972038899579623442450849 = -771782222179325333442389628311 * 535654848311348671267975559. +771782222179325333442389628311 = -(-771782222179325333442389628311). +-771782222179325333442389628311 = +(-771782222179325333442389628311). +-1440 = -771782222179325333442389628311 div 535654848311348671267975559. +-439240610983246816504823351 = -771782222179325333442389628311 rem 535654848311348671267975559. +67800214851217117319241729 = -771782222179325333442389628311 band 535654848311348671267975559. +-771314367545865201888440894481 = -771782222179325333442389628311 bor 535654848311348671267975559. +-771382167760716419005760136210 = -771782222179325333442389628311 bxor 535654848311348671267975559. +771782222179325333442389628310 = bnot(-771782222179325333442389628311). +-3644638498094299663555727589154918055519413606547456 = -771782222179325333442389628311 bsl 72. +-163431243 = -771782222179325333442389628311 bsr 72. +873839764774485360398501843 = -3643612469677871 + 873839764778128972868179714. +-873839764781772585337857585 = -3643612469677871 - 873839764778128972868179714. +-3183933463445968379222577364230379716908894 = -3643612469677871 * 873839764778128972868179714. +3643612469677871 = -(-3643612469677871). +-3643612469677871 = +(-3643612469677871). +0 = -3643612469677871 div 873839764778128972868179714. +-3643612469677871 = -3643612469677871 rem 873839764778128972868179714. +873839764774733644420550656 = -3643612469677871 band 873839764778128972868179714. +-248284022048813 = -3643612469677871 bor 873839764778128972868179714. +-873839764774981928442599469 = -3643612469677871 bxor 873839764778128972868179714. +3643612469677870 = bnot(-3643612469677871). +-1865529584475069952 = -3643612469677871 bsl 9. +-7116430604840 = -3643612469677871 bsr 9. +88329617515 = 89922 + 88329527593. +-88329437671 = 89922 - 88329527593. +7942767780217746 = 89922 * 88329527593. +-89922 = -(89922). +89922 = +(89922). +0 = 89922 div 88329527593. +89922 = 89922 rem 88329527593. +65792 = 89922 band 88329527593. +88329551723 = 89922 bor 88329527593. +88329485931 = 89922 bxor 88329527593. +-89923 = bnot(89922). +56994838636861422120693272816910336 = 89922 bsl 99. +0 = 89922 bsr 99. +37972972863670164457235 = 37972972864637848691766 + -967684234531. +37972972865605532926297 = 37972972864637848691766 - -967684234531. +-36745847179383510889822181472571746 = 37972972864637848691766 * -967684234531. +-37972972864637848691766 = -(37972972864637848691766). +37972972864637848691766 = +(37972972864637848691766). +-39241078349 = 37972972864637848691766 div -967684234531. +314786422447 = 37972972864637848691766 rem -967684234531. +37972972863675535859732 = 37972972864637848691766 band -967684234531. +-5371402497 = 37972972864637848691766 bor -967684234531. +-37972972863680907262229 = 37972972864637848691766 bxor -967684234531. +-37972972864637848691767 = bnot(37972972864637848691766). +19442162106694578530184192 = 37972972864637848691766 bsl 9. +74165962626245798226 = 37972972864637848691766 bsr 9. +6279872 = 6279929 + -57. +6279986 = 6279929 - -57. +-357955953 = 6279929 * -57. +-6279929 = -(6279929). +6279929 = +(6279929). +-110174 = 6279929 div -57. +11 = 6279929 rem -57. +6279873 = 6279929 band -57. +-1 = 6279929 bor -57. +-6279874 = 6279929 bxor -57. +-6279930 = bnot(6279929). +0 = 6279929 bsl -88. +1943543888242349716091745572225024 = 6279929 bsr -88. +34392885586249287 = 34392885586249381 + -94. +34392885586249475 = 34392885586249381 - -94. +-3232931245107441814 = 34392885586249381 * -94. +-34392885586249381 = -(34392885586249381). +34392885586249381 = +(34392885586249381). +-365881761555844 = 34392885586249381 div -94. +45 = 34392885586249381 rem -94. +34392885586249376 = 34392885586249381 band -94. +-89 = 34392885586249381 bor -94. +-34392885586249465 = 34392885586249381 bxor -94. +-34392885586249382 = bnot(34392885586249381). +0 = 34392885586249381 bsl -84. +665255158340299183156934914780744590032896 = 34392885586249381 bsr -84. +-2764682352159 = -2764682352698 + 539. +-2764682353237 = -2764682352698 - 539. +-1490163788104222 = -2764682352698 * 539. +2764682352698 = -(-2764682352698). +-2764682352698 = +(-2764682352698). +-5129280802 = -2764682352698 div 539. +-420 = -2764682352698 rem 539. +514 = -2764682352698 band 539. +-2764682352673 = -2764682352698 bor 539. +-2764682353187 = -2764682352698 bxor 539. +2764682352697 = bnot(-2764682352698). +-1 = -2764682352698 bsl -52. +-12451022413408498996591198208 = -2764682352698 bsr -52. +411347001767816756104233336410 = 438724827454564951793956448838 + -27377825686748195689723112428. +466102653141313147483679561266 = 438724827454564951793956448838 - -27377825686748195689723112428. +-12011331850499758360055954360069623806117771462827503958664 = 438724827454564951793956448838 * -27377825686748195689723112428. +-438724827454564951793956448838 = -(438724827454564951793956448838). +438724827454564951793956448838 = +(438724827454564951793956448838). +-16 = 438724827454564951793956448838 div -27377825686748195689723112428. +679616466593820758386649990 = 438724827454564951793956448838 rem -27377825686748195689723112428. +436229415513727871705332989956 = 438724827454564951793956448838 band -27377825686748195689723112428. +-24882413745911115601099653546 = 438724827454564951793956448838 bor -27377825686748195689723112428. +-461111829259638987306432643502 = 438724827454564951793956448838 bxor -27377825686748195689723112428. +-438724827454564951793956448839 = bnot(438724827454564951793956448838). +2903237 = 438724827454564951793956448838 bsl -77. +66298221451974587282214130220604359757665273628327936 = 438724827454564951793956448838 bsr -77. +49489484348507721380 = 49489484349336544761 + -828823381. +49489484350165368142 = 49489484349336544761 - -828823381. +-41018041742363700135669856941 = 49489484349336544761 * -828823381. +-49489484349336544761 = -(49489484349336544761). +49489484349336544761 = +(49489484349336544761). +-59710531198 = 49489484349336544761 div -828823381. +504204323 = 49489484349336544761 rem -828823381. +49489484348776325289 = 49489484349336544761 band -828823381. +-268603909 = 49489484349336544761 bor -828823381. +-49489484349044929198 = 49489484349336544761 bxor -828823381. +-49489484349336544762 = bnot(49489484349336544761). +1583663499178769432352 = 49489484349336544761 bsl 5. +1546546385916767023 = 49489484349336544761 bsr 5. +-5964308434181410553351390 = -48966654222568461613 + -5964259467527187984889777. +5964210500872965416428164 = -48966654222568461613 - -5964259467527187984889777. +292049831040084103997351697544933156260630301 = -48966654222568461613 * -5964259467527187984889777. +48966654222568461613 = -(-48966654222568461613). +-48966654222568461613 = +(-48966654222568461613). +0 = -48966654222568461613 div -5964259467527187984889777. +-48966654222568461613 = -48966654222568461613 rem -5964259467527187984889777. +-5964268730447095049959357 = -48966654222568461613 band -5964259467527187984889777. +-39703734315503392033 = -48966654222568461613 bor -5964259467527187984889777. +5964229026712779546567324 = -48966654222568461613 bxor -5964259467527187984889777. +48966654222568461612 = bnot(-48966654222568461613). +-391733233780547692904 = -48966654222568461613 bsl 3. +-6120831777821057702 = -48966654222568461613 bsr 3. +-4789495265182100 = -4789495265248472 + 66372. +-4789495265314844 = -4789495265248472 - 66372. +-317888379745071583584 = -4789495265248472 * 66372. +4789495265248472 = -(-4789495265248472). +-4789495265248472 = +(-4789495265248472). +-72161382288 = -4789495265248472 div 66372. +-29336 = -4789495265248472 rem 66372. +66304 = -4789495265248472 band 66372. +-4789495265248404 = -4789495265248472 bor 66372. +-4789495265314708 = -4789495265248472 bxor 66372. +4789495265248471 = bnot(-4789495265248472). +-1115142 = -4789495265248472 bsl -32. +-20570725528589032553971712 = -4789495265248472 bsr -32. +6123210 = 6131949 + -8739. +6140688 = 6131949 - -8739. +-53587102311 = 6131949 * -8739. +-6131949 = -(6131949). +6131949 = +(6131949). +-701 = 6131949 div -8739. +5910 = 6131949 rem -8739. +6131917 = 6131949 band -8739. +-8707 = 6131949 bor -8739. +-6140624 = 6131949 bxor -8739. +-6131950 = bnot(6131949). +8020551919344756729031218299753941701989984953287274290321164245870588083001099769758356086157870363219782747805318726955028674740546508065587792294262127816212374137239461470559298462333691609017014070959373923245739782857993726237262890385083410627678458699969911445122461553439023249052980524793987072 = 6131949 bsl 987. +0 = 6131949 bsr 987. +-71521222332273642257324 = -71521222332273642293443 + 36119. +-71521222332273642329562 = -71521222332273642293443 - 36119. +-2583275029419391685996867717 = -71521222332273642293443 * 36119. +71521222332273642293443 = -(-71521222332273642293443). +-71521222332273642293443 = +(-71521222332273642293443). +-1980155107624066067 = -71521222332273642293443 div 36119. +-19470 = -71521222332273642293443 rem 36119. +1301 = -71521222332273642293443 band 36119. +-71521222332273642258625 = -71521222332273642293443 bor 36119. +-71521222332273642259926 = -71521222332273642293443 bxor 36119. +71521222332273642293442 = bnot(-71521222332273642293443). +-1117519098941775660836 = -71521222332273642293443 bsl -6. +-4577358229265513106780352 = -71521222332273642293443 bsr -6. +665326317763636533 = -777616 + 665326317764414149. +-665326317765191765 = -777616 - 665326317764414149. +-517368389914692672888784 = -777616 * 665326317764414149. +777616 = -(-777616). +-777616 = +(-777616). +0 = -777616 div 665326317764414149. +-777616 = -777616 rem 665326317764414149. +665326317764346432 = -777616 band 665326317764414149. +-709899 = -777616 bor 665326317764414149. +-665326317765056331 = -777616 bxor 665326317764414149. +777615 = bnot(-777616). +-1 = -777616 bsl -64. +-14344483339621726689427456 = -777616 bsr -64. +-742789355945246516934055414343 = -742789355945246516936898773466 + 2843359123. +-742789355945246516939742132589 = -742789355945246516936898773466 - 2843359123. +-2112016891694210972416505142862061430318 = -742789355945246516936898773466 * 2843359123. +742789355945246516936898773466 = -(-742789355945246516936898773466). +-742789355945246516936898773466 = +(-742789355945246516936898773466). +-261236559932512793930 = -742789355945246516936898773466 div 2843359123. +-1814250076 = -742789355945246516936898773466 rem 2843359123. +2684499458 = -742789355945246516936898773466 band 2843359123. +-742789355945246516936739913801 = -742789355945246516936898773466 bor 2843359123. +-742789355945246516939424413259 = -742789355945246516936898773466 bxor 2843359123. +742789355945246516936898773465 = bnot(-742789355945246516936898773466). +-1 = -742789355945246516936898773466 bsl -592. +-12039906237866742069817054125723223154051261965793698359567866550315976451949665083616194680102781002958123515976277237215956114495168853552580898628325007810674596671065137644155374117516458451655322853441536 = -742789355945246516936898773466 bsr -592. +51953632733124287146 = 51953632739515644477 + -6391357331. +51953632745907001808 = 51953632739515644477 - -6391357331. +-332054231481784927717263610887 = 51953632739515644477 * -6391357331. +-51953632739515644477 = -(51953632739515644477). +51953632739515644477 = +(51953632739515644477). +-8128732294 = 51953632739515644477 div -6391357331. +522297163 = 51953632739515644477 rem -6391357331. +51953632737822973997 = 51953632739515644477 band -6391357331. +-4698686851 = 51953632739515644477 bor -6391357331. +-51953632742521660848 = 51953632739515644477 bxor -6391357331. +-51953632739515644478 = bnot(51953632739515644477). +207814530958062577908 = 51953632739515644477 bsl 2. +12988408184878911119 = 51953632739515644477 bsr 2. +-262672270 = 5713 + -262677983. +262683696 = 5713 - -262677983. +-1500679316879 = 5713 * -262677983. +-5713 = -(5713). +5713 = +(5713). +0 = 5713 div -262677983. +5713 = 5713 rem -262677983. +4609 = 5713 band -262677983. +-262676879 = 5713 bor -262677983. +-262681488 = 5713 bxor -262677983. +-5714 = bnot(5713). +11 = 5713 bsl -9. +2925056 = 5713 bsr -9. +-568921276688204408271309170952 = -5283749879527367 + -568921276688199124521429643585. +568921276688193840771550116218 = -5283749879527367 - -568921276688199124521429643585. +3006037727161827951841235319900749663063490695 = -5283749879527367 * -568921276688199124521429643585. +5283749879527367 = -(-5283749879527367). +-5283749879527367 = +(-5283749879527367). +0 = -5283749879527367 div -568921276688199124521429643585. +-5283749879527367 = -5283749879527367 rem -568921276688199124521429643585. +-568921276688199758976725202887 = -5283749879527367 band -568921276688199124521429643585. +-4649294583968065 = -5283749879527367 bor -568921276688199124521429643585. +568921276688195109682141234822 = -5283749879527367 bxor -568921276688199124521429643585. +5283749879527366 = bnot(-5283749879527367). +-42269999036218936 = -5283749879527367 bsl 3. +-660468734940921 = -5283749879527367 bsr 3. +11904699374459 = 4233227718792 + 7671471655667. +-3438243936875 = 4233227718792 - 7671471655667. +32475086456696701729194264 = 4233227718792 * 7671471655667. +-4233227718792 = -(4233227718792). +4233227718792 = +(4233227718792). +0 = 4233227718792 div 7671471655667. +4233227718792 = 4233227718792 rem 7671471655667. +3127273111680 = 4233227718792 band 7671471655667. +8777426262779 = 4233227718792 bor 7671471655667. +5650153151099 = 4233227718792 bxor 7671471655667. +-4233227718793 = bnot(4233227718792). +0 = 4233227718792 bsl -249. +3829486576376904164635311492615690175490415617529800201345103258022357798923215887663104 = 4233227718792 bsr -249. +25125316857724427543 = 25125316857179548718 + 544878825. +25125316856634669893 = 25125316857179548718 - 544878825. +13690253126892685319494096350 = 25125316857179548718 * 544878825. +-25125316857179548718 = -(25125316857179548718). +25125316857179548718 = +(25125316857179548718). +46111751281 = 25125316857179548718 div 544878825. +496023893 = 25125316857179548718 rem 544878825. +5382184 = 25125316857179548718 band 544878825. +25125316857719045359 = 25125316857179548718 bor 544878825. +25125316857713663175 = 25125316857179548718 bxor 544878825. +-25125316857179548719 = bnot(25125316857179548718). +0 = 25125316857179548718 bsl -93. +248829085897875822412742556034438954413935558656 = 25125316857179548718 bsr -93. +-88767522295277243892987472925 = 4 + -88767522295277243892987472929. +88767522295277243892987472933 = 4 - -88767522295277243892987472929. +-355070089181108975571949891716 = 4 * -88767522295277243892987472929. +-4 = -(4). +4 = +(4). +0 = 4 div -88767522295277243892987472929. +4 = 4 rem -88767522295277243892987472929. +4 = 4 band -88767522295277243892987472929. +-88767522295277243892987472929 = 4 bor -88767522295277243892987472929. +-88767522295277243892987472933 = 4 bxor -88767522295277243892987472929. +-5 = bnot(4). +0 = 4 bsl -4. +64 = 4 bsr -4. +254705954978575608208360764 = 254712299555523954647979436 + -6344576948346439618672. +254718644132472301087598108 = 254712299555523954647979436 - -6344576948346439618672. +-1616041784220290360650451738363048745803137628992 = 254712299555523954647979436 * -6344576948346439618672. +-254712299555523954647979436 = -(254712299555523954647979436). +254712299555523954647979436 = +(254712299555523954647979436). +-40146 = 254712299555523954647979436 div -6344576948346439618672. +2913387207789716773324 = 254712299555523954647979436 rem -6344576948346439618672. +254706297445885094062916992 = 254712299555523954647979436 band -6344576948346439618672. +-342467309485854556228 = 254712299555523954647979436 bor -6344576948346439618672. +-254706639913194579917473220 = 254712299555523954647979436 bxor -6344576948346439618672. +-254712299555523954647979437 = bnot(254712299555523954647979436). +1809839741579 = 254712299555523954647979436 bsl -47. +35847569292654369877447765855454005035008 = 254712299555523954647979436 bsr -47. +-2175263430742300103586 = 7632491378239 + -2175263438374791481825. +2175263446007282860064 = 7632491378239 - -2175263438374791481825. +-16602679438794118279348731369006175 = 7632491378239 * -2175263438374791481825. +-7632491378239 = -(7632491378239). +7632491378239 = +(7632491378239). +0 = 7632491378239 div -2175263438374791481825. +7632491378239 = 7632491378239 rem -2175263438374791481825. +3092706555423 = 7632491378239 band -2175263438374791481825. +-2175263433835006659009 = 7632491378239 bor -2175263438374791481825. +-2175263436927713214432 = 7632491378239 bxor -2175263438374791481825. +-7632491378240 = bnot(7632491378239). +30529965512956 = 7632491378239 bsl 2. +1908122844559 = 7632491378239 bsr 2. +-8812069618852 = -296325119 + -8811773293733. +8811476968614 = -296325119 - -8811773293733. +2611149769866453179227 = -296325119 * -8811773293733. +296325119 = -(-296325119). +-296325119 = +(-296325119). +0 = -296325119 div -8811773293733. +-296325119 = -296325119 rem -8811773293733. +-8812060606463 = -296325119 band -8811773293733. +-9012389 = -296325119 bor -8811773293733. +8812051594074 = -296325119 bxor -8811773293733. +296325118 = bnot(-296325119). +-1 = -296325119 bsl -51. +-667264847754458942144512 = -296325119 bsr -51. +961537478172334855 = 961537478172334783 + 72. +961537478172334711 = 961537478172334783 - 72. +69230698428408104376 = 961537478172334783 * 72. +-961537478172334783 = -(961537478172334783). +961537478172334783 = +(961537478172334783). +13354687196837983 = 961537478172334783 div 72. +7 = 961537478172334783 rem 72. +8 = 961537478172334783 band 72. +961537478172334847 = 961537478172334783 bor 72. +961537478172334839 = 961537478172334783 bxor 72. +-961537478172334784 = bnot(961537478172334783). +3846149912689339132 = 961537478172334783 bsl 2. +240384369543083695 = 961537478172334783 bsr 2. +-56935718366269633695631884973 = -56935718366269633696146472629 + 514587656. +-56935718366269633696661060285 = -56935718366269633696146472629 - 514587656. +-29298417856774840267678629582825267624 = -56935718366269633696146472629 * 514587656. +56935718366269633696146472629 = -(-56935718366269633696146472629). +-56935718366269633696146472629 = +(-56935718366269633696146472629). +-110643381554938880415 = -56935718366269633696146472629 div 514587656. +-127315389 = -56935718366269633696146472629 rem 514587656. +480952328 = -56935718366269633696146472629 band 514587656. +-56935718366269633696112837301 = -56935718366269633696146472629 bor 514587656. +-56935718366269633696593789629 = -56935718366269633696146472629 bxor 514587656. +56935718366269633696146472628 = bnot(-56935718366269633696146472629). +-33865750362788801638712217592875907723541573597845853713336988398679128310391930228722966719990357450223634399287920490900190621337960232425893678083539509097136354066085984633396253311133907314718439783298422229060401777256132142149667079426124235341914505345677881203404137903510253441797823517381377673087942656 = -56935718366269633696146472629 bsl 946. +-1 = -56935718366269633696146472629 bsr 946. +5478134454819665063141 = -77499384391 + 5478134454897164447532. +-5478134454974663831923 = -77499384391 - 5478134454897164447532. +-424552047865656599895221619273012 = -77499384391 * 5478134454897164447532. +77499384391 = -(-77499384391). +-77499384391 = +(-77499384391). +0 = -77499384391 div 5478134454897164447532. +-77499384391 = -77499384391 rem 5478134454897164447532. +5478134454828428176680 = -77499384391 band 5478134454897164447532. +-8763113539 = -77499384391 bor 5478134454897164447532. +-5478134454837191290219 = -77499384391 bxor 5478134454897164447532. +77499384390 = bnot(-77499384391). +-1 = -77499384391 bsl -957. +-94406979572560835598169159724368584579513338907559188265909267851122163141033431114034831856378837816438432447149999435369909239179642280099783886954506143034676884689536633413822594071691266396363194959504310276820454223562606194235221588028210734969962226246140583709705654278369610908548257021952 = -77499384391 bsr -957. +-4849115565564 = 8187 + -4849115573751. +4849115581938 = 8187 - -4849115573751. +-39699709202299437 = 8187 * -4849115573751. +-8187 = -(8187). +8187 = +(8187). +0 = 8187 div -4849115573751. +8187 = 8187 rem -4849115573751. +4617 = 8187 band -4849115573751. +-4849115570181 = 8187 bor -4849115573751. +-4849115574798 = 8187 bxor -4849115573751. +-8188 = bnot(8187). +65496 = 8187 bsl 3. +1023 = 8187 bsr 3. +-431578567135440151878 = -431578567418864531161 + 283424379283. +-431578567702288910444 = -431578567418864531161 - 283424379283. +-122319887582538047208971236337563 = -431578567418864531161 * 283424379283. +431578567418864531161 = -(-431578567418864531161). +-431578567418864531161 = +(-431578567418864531161). +-1522729161 = -431578567418864531161 div 283424379283. +-146316159598 = -431578567418864531161 rem 283424379283. +2751987971 = -431578567418864531161 band 283424379283. +-431578567138192139849 = -431578567418864531161 bor 283424379283. +-431578567140944127820 = -431578567418864531161 bxor 283424379283. +431578567418864531160 = bnot(-431578567418864531161). +-8152288646014973407771771735780730783924224 = -431578567418864531161 bsl 74. +-1 = -431578567418864531161 bsr 74. +-495291200701 = -495246754927 + -44445774. +-495202309153 = -495246754927 - -44445774. +22011625343718828498 = -495246754927 * -44445774. +495246754927 = -(-495246754927). +-495246754927 = +(-495246754927). +11142 = -495246754927 div -44445774. +-31941019 = -495246754927 rem -44445774. +-495257646192 = -495246754927 band -44445774. +-33554509 = -495246754927 bor -44445774. +495224091683 = -495246754927 bxor -44445774. +495246754926 = bnot(-495246754927). +-68066195707570939756544 = -495246754927 bsl 37. +-4 = -495246754927 bsr 37. +-6095142424482 = -749949895633 + -5345192528849. +4595242633216 = -749949895633 - -5345192528849. +4008626579148598891616417 = -749949895633 * -5345192528849. +749949895633 = -(-749949895633). +-749949895633 = +(-749949895633). +0 = -749949895633 div -5345192528849. +-749949895633 = -749949895633 rem -5345192528849. +-5491627346897 = -749949895633 band -5345192528849. +-603515077585 = -749949895633 bor -5345192528849. +4888112269312 = -749949895633 bxor -5345192528849. +749949895632 = bnot(-749949895633). +-187487473909 = -749949895633 bsl -2. +-2999799582532 = -749949895633 bsr -2. +-621829506476310151076 = -621822948751363498914 + -6557724946652162. +-621816391026416846752 = -621822948751363498914 - -6557724946652162. +4077743863427625266245768430822752068 = -621822948751363498914 * -6557724946652162. +621822948751363498914 = -(-621822948751363498914). +-621822948751363498914 = +(-621822948751363498914). +94822 = -621822948751363498914 div -6557724946652162. +-6353859912193750 = -621822948751363498914 rem -6557724946652162. +-621827742773743976354 = -621822948751363498914 band -6557724946652162. +-1763702566174722 = -621822948751363498914 bor -6557724946652162. +621825979071177801632 = -621822948751363498914 bxor -6557724946652162. +621822948751363498913 = bnot(-621822948751363498914). +-279752784190103629808262213481877267604434642103946792685969727886783900024504628125643344380628874645015331155431963989708755535149879893839797241498386941273765158340250824404369408 = -621822948751363498914 bsl 537. +-1 = -621822948751363498914 bsr 537. +249491668436548300378842774138 = -373671939733595218 + 249491668436921972318576369356. +-249491668437295644258309964574 = -373671939733595218 - 249491668436921972318576369356. +-93228035692195627484154251188872698411363339608 = -373671939733595218 * 249491668436921972318576369356. +373671939733595218 = -(-373671939733595218). +-373671939733595218 = +(-373671939733595218). +0 = -373671939733595218 div 249491668436921972318576369356. +-373671939733595218 = -373671939733595218 rem 249491668436921972318576369356. +249491668436839922216563169932 = -373671939733595218 band 249491668436921972318576369356. +-291621837720395794 = -373671939733595218 bor 249491668436921972318576369356. +-249491668437131544054283565726 = -373671939733595218 bxor 249491668436921972318576369356. +373671939733595217 = bnot(-373671939733595218). +-1 = -373671939733595218 bsl -268. +-177226770805200883084300797497432069977324995854719724156211341765268018946668965966541256401092608 = -373671939733595218 bsr -268. +782229585818934957 = 782229158144523791 + 427674411166. +782228730470112625 = 782229158144523791 - 427674411166. +334539394606335105443403050306 = 782229158144523791 * 427674411166. +-782229158144523791 = -(782229158144523791). +782229158144523791 = +(782229158144523791). +1829029 = 782229158144523791 div 427674411166. +257563985977 = 782229158144523791 rem 427674411166. +283469946894 = 782229158144523791 band 427674411166. +782229302348988063 = 782229158144523791 bor 427674411166. +782229018879041169 = 782229158144523791 bxor 427674411166. +-782229158144523792 = bnot(782229158144523791). +0 = 782229158144523791 bsl -692. +16072779992163944869162500501258888552545266030817826252520110008131745637803626241572391467228352301587824476241604259730959710633625940025608756154401018658504704342516809504287240332863674263352125923608713986070835401588736 = 782229158144523791 bsr -692. +431372269785776272290886 = 431372269785861816229748 + -85543938862. +431372269785947360168610 = 431372269785861816229748 - -85543938862. +-36901283073323933039537842257666776 = 431372269785861816229748 * -85543938862. +-431372269785861816229748 = -(431372269785861816229748). +431372269785861816229748 = +(431372269785861816229748). +-5042698238173 = 431372269785861816229748 div -85543938862. +75589650622 = 431372269785861816229748 rem -85543938862. +431372269785858016154704 = 431372269785861816229748 band -85543938862. +-81743863818 = 431372269785861816229748 bor -85543938862. +-431372269785939760018522 = 431372269785861816229748 bxor -85543938862. +-431372269785861816229749 = bnot(431372269785861816229748). +55215650532590312477407744 = 431372269785861816229748 bsl 7. +3370095857702045439294 = 431372269785861816229748 bsr 7. +4167637475335631083 = -6411 + 4167637475335637494. +-4167637475335643905 = -6411 - 4167637475335637494. +-26718723854376771974034 = -6411 * 4167637475335637494. +6411 = -(-6411). +-6411 = +(-6411). +0 = -6411 div 4167637475335637494. +-6411 = -6411 rem 4167637475335637494. +4167637475335635188 = -6411 band 4167637475335637494. +-4105 = -6411 bor 4167637475335637494. +-4167637475335639293 = -6411 bxor 4167637475335637494. +6410 = bnot(-6411). +-1 = -6411 bsl -417. +-2169871265748113289154933268376624709806030040311811531178948314370158350139387923499667470402055521872848517269721472045355630592 = -6411 bsr -417. +-72198400604812844524850328532 = -69517263963635144889192757364 + -2681136641177699635657571168. +-66836127322457445253535186196 = -69517263963635144889192757364 - -2681136641177699635657571168. +186385283607324270996007753661156514502862074176986081152 = -69517263963635144889192757364 * -2681136641177699635657571168. +69517263963635144889192757364 = -(-69517263963635144889192757364). +-69517263963635144889192757364 = +(-69517263963635144889192757364). +25 = -69517263963635144889192757364 div -2681136641177699635657571168. +-2488847934192653997753478164 = -69517263963635144889192757364 rem -2681136641177699635657571168. +-72032475452338347505308269440 = -69517263963635144889192757364 band -2681136641177699635657571168. +-165925152474497019542059092 = -69517263963635144889192757364 bor -2681136641177699635657571168. +71866550299863850485766210348 = -69517263963635144889192757364 bxor -2681136641177699635657571168. +69517263963635144889192757363 = bnot(-69517263963635144889192757364). +-1975799476771134 = -69517263963635144889192757364 bsl -45. +-2445921281894091002472893945597486430158848 = -69517263963635144889192757364 bsr -45. +-597883 = -762 + -597121. +596359 = -762 - -597121. +455006202 = -762 * -597121. +762 = -(-762). +-762 = +(-762). +0 = -762 div -597121. +-762 = -762 rem -597121. +-597754 = -762 band -597121. +-129 = -762 bor -597121. +597625 = -762 bxor -597121. +761 = bnot(-762). +-6096 = -762 bsl 3. +-96 = -762 bsr 3. +-439134683934183283784740784307 = 782114871 + -439134683934183283785522899178. +439134683934183283786305014049 = 782114871 - -439134683934183283785522899178. +-343453766676809531488270633958147476038 = 782114871 * -439134683934183283785522899178. +-782114871 = -(782114871). +782114871 = +(782114871). +0 = 782114871 div -439134683934183283785522899178. +782114871 = 782114871 rem -439134683934183283785522899178. +605552662 = 782114871 band -439134683934183283785522899178. +-439134683934183283785346336969 = 782114871 bor -439134683934183283785522899178. +-439134683934183283785951889631 = 782114871 bxor -439134683934183283785522899178. +-782114872 = bnot(782114871). +1761166120798261774123008 = 782114871 bsl 51. +0 = 782114871 bsr 51. +-2817223291852954659512177 = -2817223291852954658876965 + -635212. +-2817223291852954658241753 = -2817223291852954658876965 - -635212. +1789534041664499034774554691580 = -2817223291852954658876965 * -635212. +2817223291852954658876965 = -(-2817223291852954658876965). +-2817223291852954658876965 = +(-2817223291852954658876965). +4435091421215207928 = -2817223291852954658876965 div -635212. +-516229 = -2817223291852954658876965 rem -635212. +-2817223291852954659438448 = -2817223291852954658876965 band -635212. +-73729 = -2817223291852954658876965 bor -635212. +2817223291852954659364719 = -2817223291852954658876965 bxor -635212. +2817223291852954658876964 = bnot(-2817223291852954658876965). +-5502389241900302068120 = -2817223291852954658876965 bsl -9. +-1442418325428712785345006080 = -2817223291852954658876965 bsr -9. +-131461936887 = -54764697521 + -76697239366. +21932541845 = -54764697521 - -76697239366. +4200301114574723811686 = -54764697521 * -76697239366. +54764697521 = -(-54764697521). +-54764697521 = +(-54764697521). +0 = -54764697521 div -76697239366. +-54764697521 = -54764697521 rem -76697239366. +-128240517110 = -54764697521 band -76697239366. +-3221419777 = -54764697521 bor -76697239366. +125019097333 = -54764697521 bxor -76697239366. +54764697520 = bnot(-54764697521). +-1 = -54764697521 bsl -292. +-435772105794347831388572420830297697694089413640651371434988576327209811006398295311758623628066816 = -54764697521 bsr -292. +-718383814066737940583 = -718384471966434468442 + 657899696527859. +-718385129866130996301 = -718384471966434468442 - 657899696527859. +-472624926097043467979643525709325678 = -718384471966434468442 * 657899696527859. +718384471966434468442 = -(-718384471966434468442). +-718384471966434468442 = +(-718384471966434468442). +-1091936 = -718384471966434468442 div 657899696527859. +-108938590223418 = -718384471966434468442 rem 657899696527859. +313869310370 = -718384471966434468442 band 657899696527859. +-718383814380607250953 = -718384471966434468442 bor 657899696527859. +-718383814694476561323 = -718384471966434468442 bxor 657899696527859. +718384471966434468441 = bnot(-718384471966434468442). +-11224757374475538570 = -718384471966434468442 bsl -6. +-45976606205851805980288 = -718384471966434468442 bsr -6. +69587853318633335 = 69587853318632789 + 546. +69587853318632243 = 69587853318632789 - 546. +37994967911973502794 = 69587853318632789 * 546. +-69587853318632789 = -(69587853318632789). +69587853318632789 = +(69587853318632789). +127450280803356 = 69587853318632789 div 546. +413 = 69587853318632789 rem 546. +0 = 69587853318632789 band 546. +69587853318633335 = 69587853318632789 bor 546. +69587853318633335 = 69587853318632789 bxor 546. +-69587853318632790 = bnot(69587853318632789). +2226811306196249248 = 69587853318632789 bsl 5. +2174620416207274 = 69587853318632789 bsr 5. +7881966812303549621 = 7881967199162492797 + -386858943176. +7881967586021435973 = 7881967199162492797 - -386858943176. +-3049209500815898675745132303272 = 7881967199162492797 * -386858943176. +-7881967199162492797 = -(7881967199162492797). +7881967199162492797 = +(7881967199162492797). +-20374266 = 7881967199162492797 div -386858943176. +186415783981 = 7881967199162492797 rem -386858943176. +7881966889655100728 = 7881967199162492797 band -386858943176. +-77351551107 = 7881967199162492797 bor -386858943176. +-7881966967006651835 = 7881967199162492797 bxor -386858943176. +-7881967199162492798 = bnot(7881967199162492797). +0 = 7881967199162492797 bsl -87. +1219675348022161883312283936183914520501026816 = 7881967199162492797 bsr -87. +5434826832880908507321 = 5491168191821856 + 5434821341712716685465. +-5434815850544524863609 = 5491168191821856 - 5434821341712716685465. +29843518079847451852035006528064523040 = 5491168191821856 * 5434821341712716685465. +-5491168191821856 = -(5491168191821856). +5491168191821856 = +(5491168191821856). +0 = 5491168191821856 div 5434821341712716685465. +5491168191821856 = 5491168191821856 rem 5434821341712716685465. +2267748507648 = 5491168191821856 band 5434821341712716685465. +5434826830613159999673 = 5491168191821856 bor 5434821341712716685465. +5434826828345411492025 = 5491168191821856 bxor 5434821341712716685465. +-5491168191821857 = bnot(5491168191821856). +27694469519309956907906736988340335288164603951096450650305569038190403118530742434158245364055453483480375607197928499621306185023488 = 5491168191821856 bsl 391. +0 = 5491168191821856 bsr 391. +-12965631870144917 = -6643255557847534 + -6322376312297383. +-320879245550151 = -6643255557847534 - -6322376312297383. +42001161575473185936773981203522 = -6643255557847534 * -6322376312297383. +6643255557847534 = -(-6643255557847534). +-6643255557847534 = +(-6643255557847534). +1 = -6643255557847534 div -6322376312297383. +-320879245550151 = -6643255557847534 rem -6322376312297383. +-6753389257916400 = -6643255557847534 band -6322376312297383. +-6212242612228517 = -6643255557847534 bor -6322376312297383. +541146645687883 = -6643255557847534 bxor -6322376312297383. +6643255557847533 = bnot(-6643255557847534). +-161152725708367740895437494628907697939243534943643461141618092139904119253051381194500954345652785574706775810270689912233366294097741715204603746816563384034817788972520647289946562585108549405788710464323092207350516362491917360517306946420736 = -6643255557847534 bsl 762. +-1 = -6643255557847534 bsr 762. +31342846592922 = -26985445 + 31342873578367. +-31342900563812 = -26985445 - 31342873578367. +-845801391090975868315 = -26985445 * 31342873578367. +26985445 = -(-26985445). +-26985445 = +(-26985445). +0 = -26985445 div 31342873578367. +-26985445 = -26985445 rem 31342873578367. +31342863583259 = -26985445 band 31342873578367. +-16990337 = -26985445 bor 31342873578367. +-31342880573596 = -26985445 bxor 31342873578367. +26985444 = bnot(-26985445). +-254870321986644506167413309440 = -26985445 bsl 73. +-1 = -26985445 bsr 73. +572927541962185236192615839 = 328 + 572927541962185236192615511. +-572927541962185236192615183 = 328 - 572927541962185236192615511. +187920233763596757471177887608 = 328 * 572927541962185236192615511. +-328 = -(328). +328 = +(328). +0 = 328 div 572927541962185236192615511. +328 = 328 rem 572927541962185236192615511. +64 = 328 band 572927541962185236192615511. +572927541962185236192615775 = 328 bor 572927541962185236192615511. +572927541962185236192615711 = 328 bxor 572927541962185236192615511. +-329 = bnot(328). +0 = 328 bsl -45. +11540474045136896 = 328 bsr -45. +7522286436127792454065865 = -848625735117776 + 7522286436976418189183641. +-7522286437825043924301417 = -848625735117776 - 7522286436976418189183641. +-6383605857345588870864671022250427502416 = -848625735117776 * 7522286436976418189183641. +848625735117776 = -(-848625735117776). +-848625735117776 = +(-848625735117776). +0 = -848625735117776 div 7522286436976418189183641. +-848625735117776 = -848625735117776 rem 7522286436976418189183641. +7522286436976143037005840 = -848625735117776 band 7522286436976418189183641. +-848350582939975 = -848625735117776 bor 7522286436976418189183641. +-7522286437824493619945815 = -848625735117776 bxor 7522286436976418189183641. +848625735117775 = bnot(-848625735117776). +-230777533236791811937923527909470948120033583019220046964229501521150351925362156486191065861179888824870818927545456120268239397752217898933816374173017707522176554440297628809587477866933704705703936 = -848625735117776 bsl 616. +-1 = -848625735117776 bsr 616. +-791719256114 = -2172 + -791719253942. +791719251770 = -2172 - -791719253942. +1719614219562024 = -2172 * -791719253942. +2172 = -(-2172). +-2172 = +(-2172). +0 = -2172 div -791719253942. +-2172 = -2172 rem -791719253942. +-791719256064 = -2172 band -791719253942. +-50 = -2172 bor -791719253942. +791719256014 = -2172 bxor -791719253942. +2171 = bnot(-2172). +-1 = -2172 bsl -683. +-87165948319725549756831588940549007122614578641753643973009232494089403069559170117423124060019852570076042239041283331853318838862603927541455182509276467942068068036582806909731244523046485457712165395890176 = -2172 bsr -683. +399884239982556913673 = 399884239982557689298 + -775625. +399884239982558464923 = 399884239982557689298 - -775625. +-310160213636471307761761250 = 399884239982557689298 * -775625. +-399884239982557689298 = -(399884239982557689298). +399884239982557689298 = +(399884239982557689298). +-515563887165263 = 399884239982557689298 div -775625. +574923 = 399884239982557689298 rem -775625. +399884239982557143058 = 399884239982557689298 band -775625. +-229385 = 399884239982557689298 bor -775625. +-399884239982557372443 = 399884239982557689298 bxor -775625. +-399884239982557689299 = bnot(399884239982557689298). +6248191249727463895 = 399884239982557689298 bsl -6. +25592591358883692115072 = 399884239982557689298 bsr -6. +-44980302852142023255246380639 = -446625714922843593693761866 + -44533677137219179661552618773. +44087051422296336067858856907 = -446625714922843593693761866 - -44533677137219179661552618773. +19889885389553610740544285445999387722022564646143110418 = -446625714922843593693761866 * -44533677137219179661552618773. +446625714922843593693761866 = -(-446625714922843593693761866). +-446625714922843593693761866 = +(-446625714922843593693761866). +0 = -446625714922843593693761866 div -44533677137219179661552618773. +-446625714922843593693761866 = -446625714922843593693761866 rem -44533677137219179661552618773. +-44553095738867805362119875934 = -446625714922843593693761866 band -44533677137219179661552618773. +-427207113274217893126504705 = -446625714922843593693761866 bor -44533677137219179661552618773. +44125888625593587468993371229 = -446625714922843593693761866 bxor -44533677137219179661552618773. +446625714922843593693761865 = bnot(-446625714922843593693761866). +-26336697907466707431452259915040757780966340589709535579395555585980697709376097601034270890825071371732371680377763343497440940619798904912648202171728902307721468032616760270952556509102342144 = -446625714922843593693761866 bsl 554. +-1 = -446625714922843593693761866 bsr 554. +-75684508410009542805739174389 = -498153796625829811465951162 + -75186354613383712994273223227. +74688200816757883182807272065 = -498153796625829811465951162 - -75186354613383712994273223227. +37454368005113071165177808884019876888070327805106039774 = -498153796625829811465951162 * -75186354613383712994273223227. +498153796625829811465951162 = -(-498153796625829811465951162). +-498153796625829811465951162 = +(-498153796625829811465951162). +0 = -498153796625829811465951162 div -75186354613383712994273223227. +-498153796625829811465951162 = -498153796625829811465951162 rem -75186354613383712994273223227. +-75510346904256744945233131452 = -498153796625829811465951162 band -75186354613383712994273223227. +-174161505752797860506042937 = -498153796625829811465951162 bor -75186354613383712994273223227. +75336185398503947084727088515 = -498153796625829811465951162 bxor -75186354613383712994273223227. +498153796625829811465951161 = bnot(-498153796625829811465951162). +-72729507697548556594247865846124256119427484441651488108647007093339614933858206268651285532108070827403091989906633866101143522475573303639107187558734195229322724513812266307402531853259074857977300118498648191385206784 = -498153796625829811465951162 bsl 645. +-1 = -498153796625829811465951162 bsr 645. +-349641534929400177572 = -3662276865181 + -349641531267123312391. +349641527604846447210 = -3662276865181 - -349641531267123312391. +1280484091066044959231076453757771 = -3662276865181 * -349641531267123312391. +3662276865181 = -(-3662276865181). +-3662276865181 = +(-3662276865181). +0 = -3662276865181 div -349641531267123312391. +-3662276865181 = -3662276865181 rem -349641531267123312391. +-349641534843492171679 = -3662276865181 band -349641531267123312391. +-85908005893 = -3662276865181 bor -349641531267123312391. +349641534757584165786 = -3662276865181 bxor -349641531267123312391. +3662276865180 = bnot(-3662276865181). +-1 = -3662276865181 bsl -67. +-540456672472489650321132741459968 = -3662276865181 bsr -67. +95194355719099220632332 = 95194355719153182466249 + -53961833917. +95194355719207144300166 = 95194355719153182466249 - -53961833917. +-5136862013152763128125724995967333 = 95194355719153182466249 * -53961833917. +-95194355719153182466249 = -(95194355719153182466249). +95194355719153182466249 = +(95194355719153182466249). +-1764105272359 = 95194355719153182466249 div -53961833917. +12773666046 = 95194355719153182466249 rem -53961833917. +95194355719150760247361 = 95194355719153182466249 band -53961833917. +-51539615029 = 95194355719153182466249 bor -53961833917. +-95194355719202299862390 = 95194355719153182466249 bxor -53961833917. +-95194355719153182466250 = bnot(95194355719153182466249). +11899294464894147808281 = 95194355719153182466249 bsl -3. +761554845753225459729992 = 95194355719153182466249 bsr -3. +865761194182852538761799504 = 865761194182852485987565723 + 52774233781. +865761194182852433213331942 = 865761194182852485987565723 - 52774233781. +45689883660323594356944820124704288663 = 865761194182852485987565723 * 52774233781. +-865761194182852485987565723 = -(865761194182852485987565723). +865761194182852485987565723 = +(865761194182852485987565723). +16404997896805987 = 865761194182852485987565723 div 52774233781. +14849118876 = 865761194182852485987565723 rem 52774233781. +26607761 = 865761194182852485987565723 band 52774233781. +865761194182852538735191743 = 865761194182852485987565723 bor 52774233781. +865761194182852538708583982 = 865761194182852485987565723 bxor 52774233781. +-865761194182852485987565724 = bnot(865761194182852485987565723). +0 = 865761194182852485987565723 bsl -234. +23901056636578152198835723665750983422335028724869521276981945661302774128209516129727702244524032 = 865761194182852485987565723 bsr -234. +22552956143687134 = -2377925557 + 22552958521612691. +-22552960899538248 = -2377925557 - 22552958521612691. +-53629256454503754784443887 = -2377925557 * 22552958521612691. +2377925557 = -(-2377925557). +-2377925557 = +(-2377925557). +0 = -2377925557 div 22552958521612691. +-2377925557 = -2377925557 rem 22552958521612691. +22552956222085123 = -2377925557 band 22552958521612691. +-78397989 = -2377925557 bor 22552958521612691. +-22552956300483112 = -2377925557 bxor 22552958521612691. +2377925556 = bnot(-2377925557). +-864184189159900223931269425922722087985704133795314350665511079338331311401567617994038073478470737101191118267652517926430688278248306503581696 = -2377925557 bsl 447. +-1 = -2377925557 bsr 447. +52736489523359951 = 8 + 52736489523359943. +-52736489523359935 = 8 - 52736489523359943. +421891916186879544 = 8 * 52736489523359943. +-8 = -(8). +8 = +(8). +0 = 8 div 52736489523359943. +8 = 8 rem 52736489523359943. +0 = 8 band 52736489523359943. +52736489523359951 = 8 bor 52736489523359943. +52736489523359951 = 8 bxor 52736489523359943. +-9 = bnot(8). +943490606205385338060388645247067222729230305104110107094051575061406040598037213021531681294414691885367093757690961224942646157481198158140358562858174010912348831744 = 8 bsl 555. +0 = 8 bsr 555. +6473257884965793731994114438 = -685361747213 + 6473257884965794417355861651. +-6473257884965795102717608864 = -685361747213 - 6473257884965794417355861651. +-4436523334200485826619574672716462828663 = -685361747213 * 6473257884965794417355861651. +685361747213 = -(-685361747213). +-685361747213 = +(-685361747213). +0 = -685361747213 div 6473257884965794417355861651. +-685361747213 = -685361747213 rem 6473257884965794417355861651. +6473257884965794391582124691 = -685361747213 band 6473257884965794417355861651. +-659588010253 = -685361747213 bor 6473257884965794417355861651. +-6473257884965795051170134944 = -685361747213 bxor 6473257884965794417355861651. +685361747212 = bnot(-685361747213). +-398103322863127778168772896219995089013190570480005198583607340512926062411749281505673152733301559458222748590173533454802569120231995000055804716173753625150327419277696152317604800338665813575874556829151703700450096632420017690406582733979166862176980635624381604665642256255139974393888768 = -685361747213 bsl 936. +-1 = -685361747213 bsr 936. +9739756856122388822877 = -2488 + 9739756856122388825365. +-9739756856122388827853 = -2488 - 9739756856122388825365. +-24232515058032503397508120 = -2488 * 9739756856122388825365. +2488 = -(-2488). +-2488 = +(-2488). +0 = -2488 div 9739756856122388825365. +-2488 = -2488 rem 9739756856122388825365. +9739756856122388825088 = -2488 band 9739756856122388825365. +-2211 = -2488 bor 9739756856122388825365. +-9739756856122388827299 = -2488 bxor 9739756856122388825365. +2487 = bnot(-2488). +-1 = -2488 bsl -999. +-13329567073397165472598407610306422523383875857616838076600254831327167075994205363815387832467256475107277731094361146505328087354012386702364814502925027056094602311881343345863816808697589700496175002598389814879575934936644066843601936668919866265726568418242058456569574710575864737225483851078303744 = -2488 bsr -999. +31877226767652310946210254518 = -4866892436167135 + 31877226767657177838646421653. +-31877226767662044731082588788 = -4866892436167135 - 31877226767657177838646421653. +-155143033841495248559827480439514486390974155 = -4866892436167135 * 31877226767657177838646421653. +4866892436167135 = -(-4866892436167135). +-4866892436167135 = +(-4866892436167135). +0 = -4866892436167135 div 31877226767657177838646421653. +-4866892436167135 = -4866892436167135 rem 31877226767657177838646421653. +31877226767656894024783110145 = -4866892436167135 band 31877226767657177838646421653. +-4583078572855627 = -4866892436167135 bor 31877226767657177838646421653. +-31877226767661477103355965772 = -4866892436167135 bxor 31877226767657177838646421653. +4866892436167134 = bnot(-4866892436167135). +-1216723109041784 = -4866892436167135 bsl -2. +-19467569744668540 = -4866892436167135 bsr -2. +-6716805724025 = -3592552651 + -6713213171374. +6709620618723 = -3592552651 - -6713213171374. +24117571775547781012474 = -3592552651 * -6713213171374. +3592552651 = -(-3592552651). +-3592552651 = +(-3592552651). +0 = -3592552651 div -6713213171374. +-3592552651 = -3592552651 rem -6713213171374. +-6716769941232 = -3592552651 band -6713213171374. +-35782793 = -3592552651 bor -6713213171374. +6716734158439 = -3592552651 bxor -6713213171374. +3592552650 = bnot(-3592552651). +-14033409 = -3592552651 bsl -8. +-919693478656 = -3592552651 bsr -8. +6342688856832569926635 = 243589238 + 6342688856832326337397. +-6342688856832082748159 = 243589238 - 6342688856832326337397. +1545010745506877466293866133486 = 243589238 * 6342688856832326337397. +-243589238 = -(243589238). +243589238 = +(243589238). +0 = 243589238 div 6342688856832326337397. +243589238 = 243589238 rem 6342688856832326337397. +234913908 = 243589238 band 6342688856832326337397. +6342688856832335012727 = 243589238 bor 6342688856832326337397. +6342688856832100098819 = 243589238 bxor 6342688856832326337397. +-243589239 = bnot(243589238). +7794855616 = 243589238 bsl 5. +7612163 = 243589238 bsr 5. +-66498536559289764002685355478 = -661563588547 + -66498536559289763341121766931. +66498536559289762679558178384 = -661563588547 - -66498536559289763341121766931. +43993010479287610065554884623365714939257 = -661563588547 * -66498536559289763341121766931. +661563588547 = -(-661563588547). +-661563588547 = +(-661563588547). +0 = -661563588547 div -66498536559289763341121766931. +-661563588547 = -661563588547 rem -66498536559289763341121766931. +-66498536559289763452790996947 = -661563588547 band -66498536559289763341121766931. +-549894358531 = -661563588547 bor -66498536559289763341121766931. +66498536559289762902896638416 = -661563588547 bxor -66498536559289763341121766931. +661563588546 = bnot(-661563588547). +-1 = -661563588547 bsl -931. +-12008743190950049197359166028745504918110862504433494660009085601342677414452326029787292755507771918146614791028819877647480428524086999078135313170114862205662956040149928337601463362981762236859328550390963427343128800748578481098842371714721549472086991926143438587884108107257246652563456 = -661563588547 bsr -931. +2478045 = 776 + 2477269. +-2476493 = 776 - 2477269. +1922360744 = 776 * 2477269. +-776 = -(776). +776 = +(776). +0 = 776 div 2477269. +776 = 776 rem 2477269. +0 = 776 band 2477269. +2478045 = 776 bor 2477269. +2478045 = 776 bxor 2477269. +-777 = bnot(776). +0 = 776 bsl -765. +150594254953168766709451010380862747859917943660319571280488047688526942410578557974095205656378708361197309877621714100998643264279136995970095865678994570502832132674022440838375732706265049148050510921790497468836606144820157612032 = 776 bsr -765. +-5804070374514233830 = -5896262786855451155 + 92192412341217325. +-5988455199196668480 = -5896262786855451155 - 92192412341217325. +-543590690117952952955498064777260375 = -5896262786855451155 * 92192412341217325. +5896262786855451155 = -(-5896262786855451155). +-5896262786855451155 = +(-5896262786855451155). +-63 = -5896262786855451155 div 92192412341217325. +-88140809358759680 = -5896262786855451155 rem 92192412341217325. +1125900510822445 = -5896262786855451155 band 92192412341217325. +-5805196275025056275 = -5896262786855451155 bor 92192412341217325. +-5806322175535878720 = -5896262786855451155 bxor 92192412341217325. +5896262786855451154 = bnot(-5896262786855451155). +-1 = -5896262786855451155 bsl -769. +-18308109307104973221907306379181569546935285356107783425114666977827898124798039943215443809688591451372916367417021091895961849411086899368966313551780601272324189197241852897140354823763739530137256577861266851140500438226450994295781619332924047360 = -5896262786855451155 bsr -769. +-443211342895884 = -443211342896345 + 461. +-443211342896806 = -443211342896345 - 461. +-204320429075215045 = -443211342896345 * 461. +443211342896345 = -(-443211342896345). +-443211342896345 = +(-443211342896345). +-961412891315 = -443211342896345 div 461. +-130 = -443211342896345 rem 461. +261 = -443211342896345 band 461. +-443211342896145 = -443211342896345 bor 461. +-443211342896406 = -443211342896345 bxor 461. +443211342896344 = bnot(-443211342896345). +-816729958176514552203192674502448526511752999823230523651292759264447583415583111736446478648044233525141009345655080859402927179022658877860939660281020224748231941212147957104640 = -443211342896345 bsl 549. +-1 = -443211342896345 bsr 549. +89113643731118361834094922652 = 88487169551642615174247139488 + 626474179475746659847783164. +87860695372166868514399356324 = 88487169551642615174247139488 - 626474179475746659847783164. +55434926938996580796277853360910097493380621825085980032 = 88487169551642615174247139488 * 626474179475746659847783164. +-88487169551642615174247139488 = -(88487169551642615174247139488). +88487169551642615174247139488 = +(88487169551642615174247139488). +141 = 88487169551642615174247139488 div 626474179475746659847783164. +154310245562336135709713364 = 88487169551642615174247139488 rem 626474179475746659847783164. +2517041061918882394161312 = 88487169551642615174247139488 band 626474179475746659847783164. +89111126690056442951700761340 = 88487169551642615174247139488 bor 626474179475746659847783164. +89108609648994524069306600028 = 88487169551642615174247139488 bxor 626474179475746659847783164. +-88487169551642615174247139489 = bnot(88487169551642615174247139488). +345653006061103965524402888 = 88487169551642615174247139488 bsl -8. +22652715405220509484607267708928 = 88487169551642615174247139488 bsr -8. +-4252961282927655944807871 = -4252961282927655944727952 + -79919. +-4252961282927655944648033 = -4252961282927655944727952 - -79919. +339892412770295335446713195888 = -4252961282927655944727952 * -79919. +4252961282927655944727952 = -(-4252961282927655944727952). +-4252961282927655944727952 = +(-4252961282927655944727952). +53215897132442297134 = -4252961282927655944727952 div -79919. +-75806 = -4252961282927655944727952 rem -79919. +-4252961282927655944797616 = -4252961282927655944727952 band -79919. +-10255 = -4252961282927655944727952 bor -79919. +4252961282927655944787361 = -4252961282927655944727952 bxor -79919. +4252961282927655944727951 = bnot(-4252961282927655944727952). +-140426011681400209026547427003774677314553319113895083364477823906168064213545836899087212036304588754345279546615537065261329107956356443202764600141444295955266753800881336952656684971045506141440117127722873350801409015632681065196238844967911192617187951283431435238988282881545167534292992 = -4252961282927655944727952 bsl 892. +-1 = -4252961282927655944727952 bsr 892. +453762865478398111269668210 = -49 + 453762865478398111269668259. +-453762865478398111269668308 = -49 - 453762865478398111269668259. +-22234380408441507452213744691 = -49 * 453762865478398111269668259. +49 = -(-49). +-49 = +(-49). +0 = -49 div 453762865478398111269668259. +-49 = -49 rem 453762865478398111269668259. +453762865478398111269668227 = -49 band 453762865478398111269668259. +-17 = -49 bor 453762865478398111269668259. +-453762865478398111269668244 = -49 bxor 453762865478398111269668259. +48 = bnot(-49). +-1683627180032 = -49 bsl 35. +-1 = -49 bsr 35. +-57713179591551324250701492252 = -57713179591551319632367534597 + -4618333957655. +-57713179591551315014033576942 = -57713179591551319632367534597 - -4618333957655. +266538737111902982398789855692898145490035 = -57713179591551319632367534597 * -4618333957655. +57713179591551319632367534597 = -(-57713179591551319632367534597). +-57713179591551319632367534597 = +(-57713179591551319632367534597). +12496536656014303 = -57713179591551319632367534597 div -4618333957655. +-4300091195132 = -57713179591551319632367534597 rem -4618333957655. +-57713179591551319852619132439 = -57713179591551319632367534597 band -4618333957655. +-4398082359813 = -57713179591551319632367534597 bor -4618333957655. +57713179591551315454536772626 = -57713179591551319632367534597 bxor -4618333957655. +57713179591551319632367534596 = bnot(-57713179591551319632367534597). +-3693643493859284456471522214208 = -57713179591551319632367534597 bsl 6. +-901768431117989369255742729 = -57713179591551319632367534597 bsr 6. +265837649729404089302891 = 52315144254666596 + 265837597414259834636295. +-265837545099115579969699 = 52315144254666596 - 265837597414259834636295. +13907332257040986924721914497828145701820 = 52315144254666596 * 265837597414259834636295. +-52315144254666596 = -(52315144254666596). +52315144254666596 = +(52315144254666596). +0 = 52315144254666596 div 265837597414259834636295. +52315144254666596 = 52315144254666596 rem 265837597414259834636295. +36183072789757956 = 52315144254666596 band 265837597414259834636295. +265837613546331299544935 = 52315144254666596 bor 265837597414259834636295. +265837577363258509786979 = 52315144254666596 bxor 265837597414259834636295. +-52315144254666597 = bnot(52315144254666596). +13968058738787516388706915168375689068407128218376520265019126620449392236038299189412454557317871103017234726912 = 52315144254666596 bsl 317. +0 = 52315144254666596 bsr 317. +5116298099 = 5179827677 + -63529578. +5243357255 = 5179827677 - -63529578. +-329072266432530306 = 5179827677 * -63529578. +-5179827677 = -(5179827677). +5179827677 = +(5179827677). +-81 = 5179827677 div -63529578. +33931859 = 5179827677 rem -63529578. +5170824596 = 5179827677 band -63529578. +-54526497 = 5179827677 bor -63529578. +-5225351093 = 5179827677 bxor -63529578. +-5179827678 = bnot(5179827677). +0 = 5179827677 bsl -39. +2847640380368723378176 = 5179827677 bsr -39. +-5273151 = 444 + -5273595. +5274039 = 444 - -5273595. +-2341476180 = 444 * -5273595. +-444 = -(444). +444 = +(444). +0 = 444 div -5273595. +444 = 444 rem -5273595. +4 = 444 band -5273595. +-5273155 = 444 bor -5273595. +-5273159 = 444 bxor -5273595. +-445 = bnot(444). +0 = 444 bsl -615. +60371268815525015505453353909579794056790872133325356518541618524410670228023909318704166657475021526268636746724722291408353593834957315660243678866525384771343637568234134848022345940992 = 444 bsr -615. +494826194665397615344866324725 = 494826194665397615344865332937 + 991788. +494826194665397615344864341149 = 494826194665397615344865332937 - 991788. +490762681954805370127653298822921356 = 494826194665397615344865332937 * 991788. +-494826194665397615344865332937 = -(494826194665397615344865332937). +494826194665397615344865332937 = +(494826194665397615344865332937). +498923353242222748556007 = 494826194665397615344865332937 div 991788. +262421 = 494826194665397615344865332937 rem 991788. +328200 = 494826194665397615344865332937 band 991788. +494826194665397615344865996525 = 494826194665397615344865332937 bor 991788. +494826194665397615344865668325 = 494826194665397615344865332937 bxor 991788. +-494826194665397615344865332938 = bnot(494826194665397615344865332937). +140345557827981039314391893049623959037326578794917044229687953213535487381280129496170628842737120271071911974932563929194833801299266628684553435862103204230956193711098219747098614967226001563675077822808620342930577054561672425384147736363482328577856355552345156862561716239253724614734782765811613302784 = 494826194665397615344865332937 bsl 925. +0 = 494826194665397615344865332937 bsr 925. +-334577614673512267637522355505 = -334577614612144943799776698692 + -61367323837745656813. +-334577614550777619962031041879 = -334577614612144943799776698692 - -61367323837745656813. +20532132824763961997155896186806543924462337988596 = -334577614612144943799776698692 * -61367323837745656813. +334577614612144943799776698692 = -(-334577614612144943799776698692). +-334577614612144943799776698692 = +(-334577614612144943799776698692). +5452048316 = -334577614612144943799776698692 div -61367323837745656813. +-25137078336146121784 = -334577614612144943799776698692 rem -61367323837745656813. +-334577614613560205755450520560 = -334577614612144943799776698692 band -61367323837745656813. +-59952061882071834945 = -334577614612144943799776698692 bor -61367323837745656813. +334577614553608143873378685615 = -334577614612144943799776698692 bxor -61367323837745656813. +334577614612144943799776698691 = bnot(-334577614612144943799776698692). +-10455550456629529493743021835 = -334577614612144943799776698692 bsl -5. +-10706483667588638201592854358144 = -334577614612144943799776698692 bsr -5. +-21297477526471769336883823 = 93839 + -21297477526471769336977662. +21297477526471769337071501 = 93839 - -21297477526471769336977662. +-1998533993606584362812646824418 = 93839 * -21297477526471769336977662. +-93839 = -(93839). +93839 = +(93839). +0 = 93839 div -21297477526471769336977662. +93839 = 93839 rem -21297477526471769336977662. +91650 = 93839 band -21297477526471769336977662. +-21297477526471769336975473 = 93839 bor -21297477526471769336977662. +-21297477526471769337067123 = 93839 bxor -21297477526471769336977662. +-93840 = bnot(93839). +0 = 93839 bsl -42. +412708286555488256 = 93839 bsr -42. +264197895362246034877072924 = -3751257145287 + 264197895362249786134218211. +-264197895362253537391363498 = -3751257145287 - 264197895362249786134218211. +-991074242747426669479673681623388221557 = -3751257145287 * 264197895362249786134218211. +3751257145287 = -(-3751257145287). +-3751257145287 = +(-3751257145287). +0 = -3751257145287 div 264197895362249786134218211. +-3751257145287 = -3751257145287 rem 264197895362249786134218211. +264197895362249608294072353 = -3751257145287 band 264197895362249786134218211. +-3573416999429 = -3751257145287 bor 264197895362249786134218211. +-264197895362253181711071782 = -3751257145287 bxor 264197895362249786134218211. +3751257145286 = bnot(-3751257145287). +-937814286322 = -3751257145287 bsl -2. +-15005028581148 = -3751257145287 bsr -2. +-72757343598454287140636 = -72757343674813464813435 + 76359177672799. +-72757343751172642486234 = -72757343674813464813435 - 76359177672799. +-5555690932665979868743179456009254565 = -72757343674813464813435 * 76359177672799. +72757343674813464813435 = -(-72757343674813464813435). +-72757343674813464813435 = +(-72757343674813464813435). +-952830372 = -72757343674813464813435 div 76359177672799. +-7226299362207 = -72757343674813464813435 rem 76359177672799. +74913912717317 = -72757343674813464813435 band 76359177672799. +-72757343673368199857953 = -72757343674813464813435 bor 76359177672799. +-72757343748282112575270 = -72757343674813464813435 bxor 76359177672799. +72757343674813464813434 = bnot(-72757343674813464813435). +-568416747459480193855 = -72757343674813464813435 bsl -7. +-9312939990376123496119680 = -72757343674813464813435 bsr -7. +-2443173978 = 3 + -2443173981. +2443173984 = 3 - -2443173981. +-7329521943 = 3 * -2443173981. +-3 = -(3). +3 = +(3). +0 = 3 div -2443173981. +3 = 3 rem -2443173981. +3 = 3 band -2443173981. +-2443173981 = 3 bor -2443173981. +-2443173984 = 3 bxor -2443173981. +-4 = bnot(3). +805306368 = 3 bsl 28. +0 = 3 bsr 28. +-3645448931891413927754625081 = -3645448931891413927754625956 + 875. +-3645448931891413927754626831 = -3645448931891413927754625956 - 875. +-3189767815404987186785297711500 = -3645448931891413927754625956 * 875. +3645448931891413927754625956 = -(-3645448931891413927754625956). +-3645448931891413927754625956 = +(-3645448931891413927754625956). +-4166227350733044488862429 = -3645448931891413927754625956 div 875. +-581 = -3645448931891413927754625956 rem 875. +72 = -3645448931891413927754625956 band 875. +-3645448931891413927754625153 = -3645448931891413927754625956 bor 875. +-3645448931891413927754625225 = -3645448931891413927754625956 bxor 875. +3645448931891413927754625955 = bnot(-3645448931891413927754625956). +-227840558243213370484664123 = -3645448931891413927754625956 bsl -4. +-58327182910262622844074015296 = -3645448931891413927754625956 bsr -4. +64229 = 2 + 64227. +-64225 = 2 - 64227. +128454 = 2 * 64227. +-2 = -(2). +2 = +(2). +0 = 2 div 64227. +2 = 2 rem 64227. +2 = 2 band 64227. +64227 = 2 bor 64227. +64225 = 2 bxor 64227. +-3 = bnot(2). +0 = 2 bsl -342. +17917957937422433684459538244547554224973163977877196279199912807710334969441287563047019946172856926208 = 2 bsr -342. +-626757338901836109135953560 = -7541582214176877 + -626757338894294526921776683. +626757338886752944707599806 = -7541582214176877 - -626757338894294526921776683. +4726741999610040988142421334831059256358991 = -7541582214176877 * -626757338894294526921776683. +7541582214176877 = -(-7541582214176877). +-7541582214176877 = +(-7541582214176877). +0 = -7541582214176877 div -626757338894294526921776683. +-7541582214176877 = -7541582214176877 rem -626757338894294526921776683. +-626757338898942175994691183 = -7541582214176877 band -626757338894294526921776683. +-2893933141262377 = -7541582214176877 bor -626757338894294526921776683. +626757338896048242853428806 = -7541582214176877 bxor -626757338894294526921776683. +7541582214176876 = bnot(-7541582214176877). +-638132215910912451466994730205580201861516135967930979297281833843378789064718565091603858502704883635901837540941628509603367251144433729536 = -7541582214176877 bsl 415. +-1 = -7541582214176877 bsr 415. +-2284559120046200332 = 4745398416 + -2284559124791598748. +2284559129536997164 = 4745398416 - -2284559124791598748. +-10841143252044399028866783168 = 4745398416 * -2284559124791598748. +-4745398416 = -(4745398416). +4745398416 = +(4745398416). +0 = 4745398416 div -2284559124791598748. +4745398416 = 4745398416 rem -2284559124791598748. +38338560 = 4745398416 band -2284559124791598748. +-2284559120084538892 = 4745398416 bor -2284559124791598748. +-2284559120122877452 = 4745398416 bxor -2284559124791598748. +-4745398417 = bnot(4745398416). +303705498624 = 4745398416 bsl 6. +74146850 = 4745398416 bsr 6. +298778172512467885395267 = 298778172512467885395351 + -84. +298778172512467885395435 = 298778172512467885395351 - -84. +-25097366491047302373209484 = 298778172512467885395351 * -84. +-298778172512467885395351 = -(298778172512467885395351). +298778172512467885395351 = +(298778172512467885395351). +-3556883006100808159468 = 298778172512467885395351 div -84. +39 = 298778172512467885395351 rem -84. +298778172512467885395332 = 298778172512467885395351 band -84. +-65 = 298778172512467885395351 bor -84. +-298778172512467885395397 = 298778172512467885395351 bxor -84. +-298778172512467885395352 = bnot(298778172512467885395351). +0 = 298778172512467885395351 bsl -932. +10846879746341106854250683491297020349676922920531953549343983959344035170292491338416736773485060621087087608945540330413744546847830071999340448032004155221819772944774757727017866168531570434935738393729944261378667160894741412044825672639034861257924274515240621449999856178042342680768857979429584896 = 298778172512467885395351 bsr -932. +2268984308828144 = 69581485 + 2268984239246659. +-2268984169665174 = 69581485 - 2268984239246659. +157879292808377814508615 = 69581485 * 2268984239246659. +-69581485 = -(69581485). +69581485 = +(69581485). +0 = 69581485 div 2268984239246659. +69581485 = 69581485 rem 2268984239246659. +67405825 = 69581485 band 2268984239246659. +2268984241422319 = 69581485 bor 2268984239246659. +2268984174016494 = 69581485 bxor 2268984239246659. +-69581486 = bnot(69581485). +0 = 69581485 bsl -694. +5718876052055462937007598889387116086563452902110056711829245940354116255675625230745152443578140260237867922542525497080081186403510634308518282758545191993483541352254200013787566857722994263858933317597726496522240 = 69581485 bsr -694. +7902836001462 = 7899921622616 + 2914378846. +7897007243770 = 7899921622616 - 2914378846. +23023364462010065581136 = 7899921622616 * 2914378846. +-7899921622616 = -(7899921622616). +7899921622616 = +(7899921622616). +2710 = 7899921622616 div 2914378846. +1954949956 = 7899921622616 rem 2914378846. +134587480 = 7899921622616 band 2914378846. +7902701413982 = 7899921622616 bor 2914378846. +7902566826502 = 7899921622616 bxor 2914378846. +-7899921622617 = bnot(7899921622616). +500196041351084719973947319032291808337454016879701655445979098134205560779805962638448159616474260573226784074964131350101141996230429830484541064783979489766718649243075961677495618502656 = 7899921622616 bsl 584. +0 = 7899921622616 bsr 584. +69472832278273138 = 69472832278272622 + 516. +69472832278272106 = 69472832278272622 - 516. +35847981455588672952 = 69472832278272622 * 516. +-69472832278272622 = -(69472832278272622). +69472832278272622 = +(69472832278272622). +134637271857117 = 69472832278272622 div 516. +250 = 69472832278272622 rem 516. +516 = 69472832278272622 band 516. +69472832278272622 = 69472832278272622 bor 516. +69472832278272106 = 69472832278272622 bxor 516. +-69472832278272623 = bnot(69472832278272622). +271378251087002 = 69472832278272622 bsl -8. +17785045063237791232 = 69472832278272622 bsr -8. +-9782188648367 = -6133259365129 + -3648929283238. +-2484330081891 = -6133259365129 - -3648929283238. +22379829699112912901407702 = -6133259365129 * -3648929283238. +6133259365129 = -(-6133259365129). +-6133259365129 = +(-6133259365129). +1 = -6133259365129 div -3648929283238. +-2484330081891 = -6133259365129 rem -3648929283238. +-8613955305390 = -6133259365129 band -3648929283238. +-1168233342977 = -6133259365129 bor -3648929283238. +7445721962413 = -6133259365129 bxor -3648929283238. +6133259365128 = bnot(-6133259365129). +-6550281245928027744902992954685820792419231494427770677357445851271727377820455966876392907848330511124529152 = -6133259365129 bsl 319. +-1 = -6133259365129 bsr 319. +-93313685820166552986 = -98457538278635145628 + 5143852458468592642. +-103601390737103738270 = -98457538278635145628 - 5143852458468592642. +-506451050329322960710577528667879269176 = -98457538278635145628 * 5143852458468592642. +98457538278635145628 = -(-98457538278635145628). +-98457538278635145628 = +(-98457538278635145628). +-19 = -98457538278635145628 div 5143852458468592642. +-724341567731885430 = -98457538278635145628 rem 5143852458468592642. +81208305330045952 = -98457538278635145628 band 5143852458468592642. +-93394894125496598938 = -98457538278635145628 bor 5143852458468592642. +-93476102430826644890 = -98457538278635145628 bxor 5143852458468592642. +98457538278635145627 = bnot(-98457538278635145628). +-1538399035603674151 = -98457538278635145628 bsl -6. +-6301282449832649320192 = -98457538278635145628 bsr -6. +-6060 = -5229 + -831. +-4398 = -5229 - -831. +4345299 = -5229 * -831. +5229 = -(-5229). +-5229 = +(-5229). +6 = -5229 div -831. +-243 = -5229 rem -831. +-6015 = -5229 band -831. +-45 = -5229 bor -831. +5970 = -5229 bxor -831. +5228 = bnot(-5229). +-1 = -5229 bsl -76. +-395092069422805997158662144 = -5229 bsr -76. +-4343754474128429969041 = -52584374 + -4343754474128377384667. +4343754474128324800293 = -52584374 - -4343754474128377384667. +228413609831739920408471393458 = -52584374 * -4343754474128377384667. +52584374 = -(-52584374). +-52584374 = +(-52584374). +0 = -52584374 div -4343754474128377384667. +-52584374 = -52584374 rem -4343754474128377384667. +-4343754474128377536512 = -52584374 band -4343754474128377384667. +-52432529 = -52584374 bor -4343754474128377384667. +4343754474128325103983 = -52584374 bxor -4343754474128377384667. +52584373 = bnot(-52584374). +-2083081664491428131440587534952824832 = -52584374 bsl 95. +-1 = -52584374 bsr 95. +-3638 = -3631 + -7. +-3624 = -3631 - -7. +25417 = -3631 * -7. +3631 = -(-3631). +-3631 = +(-3631). +518 = -3631 div -7. +-5 = -3631 rem -7. +-3631 = -3631 band -7. +-7 = -3631 bor -7. +3624 = -3631 bxor -7. +3630 = bnot(-3631). +-908 = -3631 bsl -2. +-14524 = -3631 bsr -2. +-884549755474144167619 = -884549755474144168175 + 556. +-884549755474144168731 = -884549755474144168175 - 556. +-491809664043624157505300 = -884549755474144168175 * 556. +884549755474144168175 = -(-884549755474144168175). +-884549755474144168175 = +(-884549755474144168175). +-1590916826392345626 = -884549755474144168175 div 556. +-119 = -884549755474144168175 rem 556. +512 = -884549755474144168175 band 556. +-884549755474144168131 = -884549755474144168175 bor 556. +-884549755474144168643 = -884549755474144168175 bxor 556. +884549755474144168174 = bnot(-884549755474144168175). +-1591805238744975374454665900570029007819284350200031663884462025031376025609117149208746513976100952086165260745837921603193537457214918655990196564258865998806977944368611206784614400 = -884549755474144168175 bsl 539. +-1 = -884549755474144168175 bsr 539. +-6898178838912644673024105 = 95931631866715232 + -6898178934844276539739337. +6898179030775908406454569 = 95931631866715232 - -6898178934844276539739337. +-661753562128210935363300938280983687481184 = 95931631866715232 * -6898178934844276539739337. +-95931631866715232 = -(95931631866715232). +95931631866715232 = +(95931631866715232). +0 = 95931631866715232 div -6898178934844276539739337. +95931631866715232 = 95931631866715232 rem -6898178934844276539739337. +22607067303022624 = 95931631866715232 band -6898178934844276539739337. +-6898178861519711976046729 = 95931631866715232 bor -6898178934844276539739337. +-6898178884126779279069353 = 95931631866715232 bxor -6898178934844276539739337. +-95931631866715233 = bnot(95931631866715232). +0 = 95931631866715232 bsl -93. +950060864974336740620950611578780579207839744 = 95931631866715232 bsr -93. +432547742614636761652035 = 432547742614636761651666 + 369. +432547742614636761651297 = 432547742614636761651666 - 369. +159610117024800965049464754 = 432547742614636761651666 * 369. +-432547742614636761651666 = -(432547742614636761651666). +432547742614636761651666 = +(432547742614636761651666). +1172216104646712091196 = 432547742614636761651666 div 369. +342 = 432547742614636761651666 rem 369. +336 = 432547742614636761651666 band 369. +432547742614636761651699 = 432547742614636761651666 bor 369. +432547742614636761651363 = 432547742614636761651666 bxor 369. +-432547742614636761651667 = bnot(432547742614636761651666). +55366111054673505491413248 = 432547742614636761651666 bsl 7. +3379279239176849700403 = 432547742614636761651666 bsr 7. +-903415491 = 51542996 + -954958487. +1006501483 = 51542996 - -954958487. +-49221421475607052 = 51542996 * -954958487. +-51542996 = -(51542996). +51542996 = +(51542996). +0 = 51542996 div -954958487. +51542996 = 51542996 rem -954958487. +51411264 = 51542996 band -954958487. +-954826755 = 51542996 bor -954958487. +-1006238019 = 51542996 bxor -954958487. +-51542997 = bnot(51542996). +206171984 = 51542996 bsl 2. +12885749 = 51542996 bsr 2. +-394039090394236209 = 57478469399929949 + -451517559794166158. +508996029194096107 = 57478469399929949 - -451517559794166158. +-25952538244160020554537424066465942 = 57478469399929949 * -451517559794166158. +-57478469399929949 = -(57478469399929949). +57478469399929949 = +(57478469399929949). +0 = 57478469399929949 div -451517559794166158. +57478469399929949 = 57478469399929949 rem -451517559794166158. +38315819969545296 = 57478469399929949 band -451517559794166158. +-432354910363781505 = 57478469399929949 bor -451517559794166158. +-470670730333326801 = 57478469399929949 bxor -451517559794166158. +-57478469399929950 = bnot(57478469399929949). +898101084373905 = 57478469399929949 bsl -6. +3678622041595516736 = 57478469399929949 bsr -6. +441188502936649166298 = 7965182897847 + 441188494971466268451. +-441188487006283370604 = 7965182897847 - 441188494971466268451. +3514147054873580279719147811924997 = 7965182897847 * 441188494971466268451. +-7965182897847 = -(7965182897847). +7965182897847 = +(7965182897847). +0 = 7965182897847 div 441188494971466268451. +7965182897847 = 7965182897847 rem 441188494971466268451. +6771039383075 = 7965182897847 band 441188494971466268451. +441188496165609783223 = 7965182897847 bor 441188494971466268451. +441188489394570400148 = 7965182897847 bxor 441188494971466268451. +-7965182897848 = bnot(7965182897847). +0 = 7965182897847 bsl -395. +642752892715792032020916564971604842268294905551325536647355633728692499974443520789917622155430822468256301261612127218720409911296 = 7965182897847 bsr -395. +158154113 = -635671774 + 793825887. +-1429497661 = -635671774 - 793825887. +-504612709836413538 = -635671774 * 793825887. +635671774 = -(-635671774). +-635671774 = +(-635671774). +0 = -635671774 div 793825887. +-635671774 = -635671774 rem 793825887. +168837634 = -635671774 band 793825887. +-10683521 = -635671774 bor 793825887. +-179521155 = -635671774 bxor 793825887. +635671773 = bnot(-635671774). +-3001875079643887983740745416704 = -635671774 bsl 72. +-1 = -635671774 bsr 72. +-749159243735 = 584196 + -749159827931. +749160412127 = 584196 - -749159827931. +-437656174837978476 = 584196 * -749159827931. +-584196 = -(584196). +584196 = +(584196). +0 = 584196 div -749159827931. +584196 = 584196 rem -749159827931. +532996 = 584196 band -749159827931. +-749159776731 = 584196 bor -749159827931. +-749160309727 = 584196 bxor -749159827931. +-584197 = bnot(584196). +74777088 = 584196 bsl 7. +4564 = 584196 bsr 7. +-289323663941639762 = -824322113 + -289323663117317649. +289323662292995536 = -824322113 - -289323663117317649. +238495893321767451315872337 = -824322113 * -289323663117317649. +824322113 = -(-824322113). +-824322113 = +(-824322113). +0 = -824322113 div -289323663117317649. +-824322113 = -824322113 rem -289323663117317649. +-289323663117450833 = -824322113 band -289323663117317649. +-824188929 = -824322113 bor -289323663117317649. +289323662293261904 = -824322113 bxor -289323663117317649. +824322112 = bnot(-824322113). +-1610005 = -824322113 bsl -9. +-422052921856 = -824322113 bsr -9. +-326847 = 44525 + -371372. +415897 = 44525 - -371372. +-16535338300 = 44525 * -371372. +-44525 = -(44525). +44525 = +(44525). +0 = 44525 div -371372. +44525 = 44525 rem -371372. +1348 = 44525 band -371372. +-328195 = 44525 bor -371372. +-329543 = 44525 bxor -371372. +-44526 = bnot(44525). +6416728749077482700800 = 44525 bsl 57. +0 = 44525 bsr 57. +23581337831219595386137516208 = -3 + 23581337831219595386137516211. +-23581337831219595386137516214 = -3 - 23581337831219595386137516211. +-70744013493658786158412548633 = -3 * 23581337831219595386137516211. +3 = -(-3). +-3 = +(-3). +0 = -3 div 23581337831219595386137516211. +-3 = -3 rem 23581337831219595386137516211. +23581337831219595386137516209 = -3 band 23581337831219595386137516211. +-1 = -3 bor 23581337831219595386137516211. +-23581337831219595386137516210 = -3 bxor 23581337831219595386137516211. +2 = bnot(-3). +-1536 = -3 bsl 9. +-1 = -3 bsr 9. +473833510 = 58349 + 473775161. +-473716812 = 58349 - 473775161. +27644306869189 = 58349 * 473775161. +-58349 = -(58349). +58349 = +(58349). +0 = 58349 div 473775161. +58349 = 58349 rem 473775161. +8233 = 58349 band 473775161. +473825277 = 58349 bor 473775161. +473817044 = 58349 bxor 473775161. +-58350 = bnot(58349). +14937344 = 58349 bsl 8. +227 = 58349 bsr 8. +-33376122770 = 86 + -33376122856. +33376122942 = 86 - -33376122856. +-2870346565616 = 86 * -33376122856. +-86 = -(86). +86 = +(86). +0 = 86 div -33376122856. +86 = 86 rem -33376122856. +16 = 86 band -33376122856. +-33376122786 = 86 bor -33376122856. +-33376122802 = 86 bxor -33376122856. +-87 = bnot(86). +0 = 86 bsl -65. +3172839980678042877952 = 86 bsr -65. +-929864438874349386957477629 = -929864438874349386957477632 + 3. +-929864438874349386957477635 = -929864438874349386957477632 - 3. +-2789593316623048160872432896 = -929864438874349386957477632 * 3. +929864438874349386957477632 = -(-929864438874349386957477632). +-929864438874349386957477632 = +(-929864438874349386957477632). +-309954812958116462319159210 = -929864438874349386957477632 div 3. +-2 = -929864438874349386957477632 rem 3. +0 = -929864438874349386957477632 band 3. +-929864438874349386957477629 = -929864438874349386957477632 bor 3. +-929864438874349386957477629 = -929864438874349386957477632 bxor 3. +929864438874349386957477631 = bnot(-929864438874349386957477632). +-7438915510994795095659821056 = -929864438874349386957477632 bsl 3. +-116233054859293673369684704 = -929864438874349386957477632 bsr 3. +-3817912565748568606797 = -3817912565738985778851 + -9582827946. +-3817912565729402950905 = -3817912565738985778851 - -9582827946. +36586399230348115063269938570046 = -3817912565738985778851 * -9582827946. +3817912565738985778851 = -(-3817912565738985778851). +-3817912565738985778851 = +(-3817912565738985778851). +398411887101 = -3817912565738985778851 div -9582827946. +-8926054305 = -3817912565738985778851 rem -9582827946. +-3817912565739170987948 = -3817912565738985778851 band -9582827946. +-9397618849 = -3817912565738985778851 bor -9582827946. +3817912565729773369099 = -3817912565738985778851 bxor -9582827946. +3817912565738985778850 = bnot(-3817912565738985778851). +-1043841503321345663125349288538610526431071093780390609101774787620215813866056745943147557256981444124967678463891734528 = -3817912565738985778851 bsl 327. +-1 = -3817912565738985778851 bsr 327. +-38146852966143458950 = -38146852966148174367 + 4715417. +-38146852966152889784 = -38146852966148174367 - 4715417. +-179878318973075525929116039 = -38146852966148174367 * 4715417. +38146852966148174367 = -(-38146852966148174367). +-38146852966148174367 = +(-38146852966148174367). +-8089815379243 = -38146852966148174367 div 4715417. +-4285036 = -38146852966148174367 rem 4715417. +426369 = -38146852966148174367 band 4715417. +-38146852966143885319 = -38146852966148174367 bor 4715417. +-38146852966144311688 = -38146852966148174367 bxor 4715417. +38146852966148174366 = bnot(-38146852966148174367). +-5902939582440887005209827326210539013093195776 = -38146852966148174367 bsl 87. +-1 = -38146852966148174367 bsr 87. +27296884958896974342379 = 9828 + 27296884958896974332551. +-27296884958896974322723 = 9828 - 27296884958896974332551. +268273785376039463740311228 = 9828 * 27296884958896974332551. +-9828 = -(9828). +9828 = +(9828). +0 = 9828 div 27296884958896974332551. +9828 = 9828 rem 27296884958896974332551. +516 = 9828 band 27296884958896974332551. +27296884958896974341863 = 9828 bor 27296884958896974332551. +27296884958896974341347 = 9828 bxor 27296884958896974332551. +-9829 = bnot(9828). +157248 = 9828 bsl 4. +614 = 9828 bsr 4. +481750492244047 = 594898489335 + 481155593754712. +-480560695265377 = 594898489335 - 481155593754712. +286238735859763129337996520 = 594898489335 * 481155593754712. +-594898489335 = -(594898489335). +594898489335 = +(594898489335). +0 = 594898489335 div 481155593754712. +594898489335 = 594898489335 rem 481155593754712. +594856511568 = 594898489335 band 481155593754712. +481155635732479 = 594898489335 bor 481155593754712. +480560779220911 = 594898489335 bxor 481155593754712. +-594898489336 = bnot(594898489335). +18590577791 = 594898489335 bsl -5. +19036751658720 = 594898489335 bsr -5. +-56521177399366874777959624 = -56521177399366874777956856 + -2768. +-56521177399366874777954088 = -56521177399366874777956856 - -2768. +156450619041447509385384577408 = -56521177399366874777956856 * -2768. +56521177399366874777956856 = -(-56521177399366874777956856). +-56521177399366874777956856 = +(-56521177399366874777956856). +20419500505551616610533 = -56521177399366874777956856 div -2768. +-1512 = -56521177399366874777956856 rem -2768. +-56521177399366874777959424 = -56521177399366874777956856 band -2768. +-200 = -56521177399366874777956856 bor -2768. +56521177399366874777959224 = -56521177399366874777956856 bxor -2768. +56521177399366874777956855 = bnot(-56521177399366874777956856). +-4270619419569590861925385289086088873382212796416 = -56521177399366874777956856 bsl 76. +-749 = -56521177399366874777956856 bsr 76. +3331606320261 = -4222816969137 + 7554423289398. +-11777240258535 = -4222816969137 - 7554423289398. +-31900946858513628185309526 = -4222816969137 * 7554423289398. +4222816969137 = -(-4222816969137). +-4222816969137 = +(-4222816969137). +0 = -4222816969137 div 7554423289398. +-4222816969137 = -4222816969137 rem 7554423289398. +4435698128390 = -4222816969137 band 7554423289398. +-1104091808129 = -4222816969137 bor 7554423289398. +-5539789936519 = -4222816969137 bxor 7554423289398. +4222816969136 = bnot(-4222816969137). +-326724637791776765240250227125458567168 = -4222816969137 bsl 86. +-1 = -4222816969137 bsr 86. +-3869944912635894845431 = -3869944912635894845426 + -5. +-3869944912635894845421 = -3869944912635894845426 - -5. +19349724563179474227130 = -3869944912635894845426 * -5. +3869944912635894845426 = -(-3869944912635894845426). +-3869944912635894845426 = +(-3869944912635894845426). +773988982527178969085 = -3869944912635894845426 div -5. +-1 = -3869944912635894845426 rem -5. +-3869944912635894845430 = -3869944912635894845426 band -5. +-1 = -3869944912635894845426 bor -5. +3869944912635894845429 = -3869944912635894845426 bxor -5. +3869944912635894845425 = bnot(-3869944912635894845426). +-8115862713424192146874826752 = -3869944912635894845426 bsl 21. +-1845333534543941 = -3869944912635894845426 bsr 21. +-791938612820188974009 = 7984591332 + -791938612828173565341. +791938612836158156673 = 7984591332 - -791938612828173565341. +-6323306183463938655213284224212 = 7984591332 * -791938612828173565341. +-7984591332 = -(7984591332). +7984591332 = +(7984591332). +0 = 7984591332 div -791938612828173565341. +7984591332 = 7984591332 rem -791938612828173565341. +3641376864 = 7984591332 band -791938612828173565341. +-791938612823830350873 = 7984591332 bor -791938612828173565341. +-791938612827471727737 = 7984591332 bxor -791938612828173565341. +-7984591333 = bnot(7984591332). +152795239135758123610193604886969735300219218331318199952071007164863589275883561950294154464429070843944911676374127825687842495580767193068162538932842201844502675203742537259543974199411276738883515609776128 = 7984591332 bsl 662. +0 = 7984591332 bsr 662. +-95762135561856276171733400868 = -322622315345758699 + -95762135561533653856387642169. +95762135561211031541041883470 = -322622315345758699 - -95762135561533653856387642169. +30895001897316403762773969256055325231030978131 = -322622315345758699 * -95762135561533653856387642169. +322622315345758699 = -(-322622315345758699). +-322622315345758699 = +(-322622315345758699). +0 = -322622315345758699 div -95762135561533653856387642169. +-322622315345758699 = -322622315345758699 rem -95762135561533653856387642169. +-95762135561847268696518360059 = -322622315345758699 band -95762135561533653856387642169. +-9007475215040809 = -322622315345758699 bor -95762135561533653856387642169. +95762135561838261221303319250 = -322622315345758699 bxor -95762135561533653856387642169. +322622315345758698 = bnot(-322622315345758699). +-2567161184092343845628212333860085140646302889367202631469553957315392947157823861052588997808445984866304 = -322622315345758699 bsl 292. +-1 = -322622315345758699 bsr 292. +-99095 = -6558 + -92537. +85979 = -6558 - -92537. +606857646 = -6558 * -92537. +6558 = -(-6558). +-6558 = +(-6558). +0 = -6558 div -92537. +-6558 = -6558 rem -92537. +-96766 = -6558 band -92537. +-2329 = -6558 bor -92537. +94437 = -6558 bxor -92537. +6557 = bnot(-6558). +-606859543878319811624706237634247050128856807962137244692439035497596391899422384533757007425919985914188536281096075659160210009175834225362040755136016959601808532043977599179663642833949482510332748217129266385338025669296128 = -6558 bsl 744. +-1 = -6558 bsr 744. +-4816162758613654499450998419 = -4816162758613654499451532177 + 533758. +-4816162758613654499452065935 = -4816162758613654499451532177 - 533758. +-2570665401712106998318250911731166 = -4816162758613654499451532177 * 533758. +4816162758613654499451532177 = -(-4816162758613654499451532177). +-4816162758613654499451532177 = +(-4816162758613654499451532177). +-9023120512692370886153 = -4816162758613654499451532177 div 533758. +-279203 = -4816162758613654499451532177 rem 533758. +1134 = -4816162758613654499451532177 band 533758. +-4816162758613654499450999553 = -4816162758613654499451532177 bor 533758. +-4816162758613654499451000687 = -4816162758613654499451532177 bxor 533758. +4816162758613654499451532176 = bnot(-4816162758613654499451532177). +-875143398867689885702861582865761345058340424630704765607334381359968415311325768611320589070116093115457035529403987868423505377358747196387899692483366279446528 = -4816162758613654499451532177 bsl 446. +-1 = -4816162758613654499451532177 bsr 446. +-234214727464624993697749987957 = 45666987 + -234214727464624993697795654944. +234214727464624993697841321931 = 45666987 - -234214727464624993697795654944. +-10695880914335572547072316102984133728 = 45666987 * -234214727464624993697795654944. +-45666987 = -(45666987). +45666987 = +(45666987). +0 = 45666987 div -234214727464624993697795654944. +45666987 = 45666987 rem -234214727464624993697795654944. +2626208 = 45666987 band -234214727464624993697795654944. +-234214727464624993697752614165 = 45666987 bor -234214727464624993697795654944. +-234214727464624993697755240373 = 45666987 bxor -234214727464624993697795654944. +-45666988 = bnot(45666987). +0 = 45666987 bsl -814. +4989061176068287327376163286037207456904942639896041682600096896425602836184001940372722721400138276293043823722192536810459596531044311721135428994959988087426858384533388806703417525251556871597511867028804791274242795579764130948539744305141942059008 = 45666987 bsr -814. +294237733793 = 294237675975 + 57818. +294237618157 = 294237675975 - 57818. +17012233949522550 = 294237675975 * 57818. +-294237675975 = -(294237675975). +294237675975 = +(294237675975). +5089032 = 294237675975 div 57818. +23799 = 294237675975 rem 57818. +41410 = 294237675975 band 57818. +294237692383 = 294237675975 bor 57818. +294237650973 = 294237675975 bxor 57818. +-294237675976 = bnot(294237675975). +2298731843 = 294237675975 bsl -7. +37662422524800 = 294237675975 bsr -7. +619635526811414968622238 = 619635526811414968622274 + -36. +619635526811414968622310 = 619635526811414968622274 - -36. +-22306878965210938870401864 = 619635526811414968622274 * -36. +-619635526811414968622274 = -(619635526811414968622274). +619635526811414968622274 = +(619635526811414968622274). +-17212097966983749128396 = 619635526811414968622274 div -36. +18 = 619635526811414968622274 rem -36. +619635526811414968622272 = 619635526811414968622274 band -36. +-34 = 619635526811414968622274 bor -36. +-619635526811414968622306 = 619635526811414968622274 bxor -36. +-619635526811414968622275 = bnot(619635526811414968622274). +0 = 619635526811414968622274 bsl -898. +1309400240447349610752865658212333969519436336204740814484295543713792185287997964704284463880988952952448374164567391624130625099714206654273655760270277077772585340072874724861337858038465105456883583603200323496638775911839793771182071797910195619316242423523255972536276419270994033698144256 = 619635526811414968622274 bsr -898. +9775526678384975794014685742 = -33684429226 + 9775526678384975827699114968. +-9775526678384975861383544194 = -33684429226 - 9775526678384975827699114968. +-329283036544933582249851608562433254768 = -33684429226 * 9775526678384975827699114968. +33684429226 = -(-33684429226). +-33684429226 = +(-33684429226). +0 = -33684429226 div 9775526678384975827699114968. +-33684429226 = -33684429226 rem 9775526678384975827699114968. +9775526678384975806094910032 = -33684429226 band 9775526678384975827699114968. +-12080224290 = -33684429226 bor 9775526678384975827699114968. +-9775526678384975818175134322 = -33684429226 bxor 9775526678384975827699114968. +33684429225 = bnot(-33684429226). +-121887201088907928216526935522257963350171324723121089166932176873234351228518345474048 = -33684429226 bsl 251. +-1 = -33684429226 bsr 251. +9086916786367603 = -34196395468764 + 9121113181836367. +-9155309577305131 = -34196395468764 - 9121113181836367. +-311909193481432730867307740388 = -34196395468764 * 9121113181836367. +34196395468764 = -(-34196395468764). +-34196395468764 = +(-34196395468764). +0 = -34196395468764 div 9121113181836367. +-34196395468764 = -34196395468764 rem 9121113181836367. +9113310836871172 = -34196395468764 band 9121113181836367. +-26394050503569 = -34196395468764 bor 9121113181836367. +-9139704887374741 = -34196395468764 bxor 9121113181836367. +34196395468763 = bnot(-34196395468764). +-21166543575010053090615518150392773869568 = -34196395468764 bsl 89. +-1 = -34196395468764 bsr 89. +999476298913469228469154575859 = 42153428 + 999476298913469228469112422431. +-999476298913469228469070269003 = 42153428 - 999476298913469228469112422431. +42131352203955403352488280722850743468 = 42153428 * 999476298913469228469112422431. +-42153428 = -(42153428). +42153428 = +(42153428). +0 = 42153428 div 999476298913469228469112422431. +42153428 = 42153428 rem 999476298913469228469112422431. +8519700 = 42153428 band 999476298913469228469112422431. +999476298913469228469146056159 = 42153428 bor 999476298913469228469112422431. +999476298913469228469137536459 = 42153428 bxor 999476298913469228469112422431. +-42153429 = bnot(42153428). +329323 = 42153428 bsl -7. +5395638784 = 42153428 bsr -7. +595927225325835812808187095571 = -494321158288683628236833357 + 596421546484124496436423928928. +-596915867642413180064660762285 = -494321158288683628236833357 - 596421546484124496436423928928. +-294823789686360385692280171002505341469922006947147651296 = -494321158288683628236833357 * 596421546484124496436423928928. +494321158288683628236833357 = -(-494321158288683628236833357). +-494321158288683628236833357 = +(-494321158288683628236833357). +0 = -494321158288683628236833357 div 596421546484124496436423928928. +-494321158288683628236833357 = -494321158288683628236833357 rem 596421546484124496436423928928. +596111740048785683094737824800 = -494321158288683628236833357 band 596421546484124496436423928928. +-184514722949870286550729229 = -494321158288683628236833357 bor 596421546484124496436423928928. +-596296254771735553381288554029 = -494321158288683628236833357 bxor 596421546484124496436423928928. +494321158288683628236833356 = bnot(-494321158288683628236833357). +-74299794547651704779075817488211167888677617799570034016983255678418711265003573368175743881415842265896826807944841365719178660594843648 = -494321158288683628236833357 bsl 366. +-1 = -494321158288683628236833357 bsr 366. +76696419294522 = -6 + 76696419294528. +-76696419294534 = -6 - 76696419294528. +-460178515767168 = -6 * 76696419294528. +6 = -(-6). +-6 = +(-6). +0 = -6 div 76696419294528. +-6 = -6 rem 76696419294528. +76696419294528 = -6 band 76696419294528. +-6 = -6 bor 76696419294528. +-76696419294534 = -6 bxor 76696419294528. +5 = bnot(-6). +-27881567033958432427463671840310635502461128781113646107295722362173887321757582003971905896802931573558726071066118244696023473353966982021078073395669899233430703258389872636425370184393082566316984920919089447613770288253960251652945605131537339056475845727265198365445600290275328 = -6 bsl 939. +-1 = -6 bsr 939. +-5963204504535392 = 612459256858577 + -6575663761393969. +7188123018252546 = 612459256858577 - -6575663761393969. +-4027326140655225441893413722113 = 612459256858577 * -6575663761393969. +-612459256858577 = -(612459256858577). +612459256858577 = +(612459256858577). +0 = 612459256858577 div -6575663761393969. +612459256858577 = 612459256858577 rem -6575663761393969. +36315161740993 = 612459256858577 band -6575663761393969. +-5999519666276385 = 612459256858577 bor -6575663761393969. +-6035834828017378 = 612459256858577 bxor -6575663761393969. +-612459256858578 = bnot(612459256858577). +0 = 612459256858577 bsl -439. +869451376832272522741917124901056592656087690916267199941797101960482731922298972310236064550080148577974253133047874586483234014371207396380901376 = 612459256858577 bsr -439. +526301200591041754927532011 = 527268739875958669246658124 + -967539284916914319126113. +528236279160875583565784237 = 527268739875958669246658124 - -967539284916914319126113. +-510153219538627557276352650964165768447981351992012 = 527268739875958669246658124 * -967539284916914319126113. +-527268739875958669246658124 = -(527268739875958669246658124). +527268739875958669246658124 = +(527268739875958669246658124). +-544 = 527268739875958669246658124 div -967539284916914319126113. +927368881157279642052652 = 527268739875958669246658124 rem -967539284916914319126113. +527248039701759342747455500 = 527268739875958669246658124 band -967539284916914319126113. +-946839110717587819923489 = 527268739875958669246658124 bor -967539284916914319126113. +-528194878812476930567378989 = 527268739875958669246658124 bxor -967539284916914319126113. +-527268739875958669246658125 = bnot(527268739875958669246658124). +1029821757570231775872379 = 527268739875958669246658124 bsl -9. +269961594816490838654288959488 = 527268739875958669246658124 bsr -9. +25 = -33 + 58. +-91 = -33 - 58. +-1914 = -33 * 58. +33 = -(-33). +-33 = +(-33). +0 = -33 div 58. +-33 = -33 rem 58. +26 = -33 band 58. +-1 = -33 bor 58. +-27 = -33 bxor 58. +32 = bnot(-33). +-1 = -33 bsl -977. +-42152147337373282422182591699338030515344570620396863276533797760273915156272521069378312231204466007006912477349345499552697890314872698114811308379775639597158519812726929488050396676904946289297638894444767674739146716812152782613332623269622692606550393553215967599486611419264865489676926976 = -33 bsr -977. +-363991769580627863095264 = 97355814189858 + -363991769677983677285122. +363991769775339491474980 = 97355814189858 - -363991769677983677285122. +-35436715095407368188328987401306692676 = 97355814189858 * -363991769677983677285122. +-97355814189858 = -(97355814189858). +97355814189858 = +(97355814189858). +0 = 97355814189858 div -363991769677983677285122. +97355814189858 = 97355814189858 rem -363991769677983677285122. +70967526733858 = 97355814189858 band -363991769677983677285122. +-363991769651595389829122 = 97355814189858 bor -363991769677983677285122. +-363991769722562916562980 = 97355814189858 bxor -363991769677983677285122. +-97355814189859 = bnot(97355814189858). +0 = 97355814189858 bsl -51. +219225804253897867858525814784 = 97355814189858 bsr -51. +-442434983275624365774696314360 = 35967576152264915259 + -442434983311591941926961229619. +442434983347559518079226144878 = 35967576152264915259 - -442434983311591941926961229619. +-15913313954685740093802190705270834339315475856321 = 35967576152264915259 * -442434983311591941926961229619. +-35967576152264915259 = -(35967576152264915259). +35967576152264915259 = +(35967576152264915259). +0 = 35967576152264915259 div -442434983311591941926961229619. +35967576152264915259 = 35967576152264915259 rem -442434983311591941926961229619. +26734058852615229449 = 35967576152264915259 band -442434983311591941926961229619. +-442434983302358424627311543809 = 35967576152264915259 bor -442434983311591941926961229619. +-442434983329092483479926773258 = 35967576152264915259 bxor -442434983311591941926961229619. +-35967576152264915260 = bnot(35967576152264915259). +143870304609059661036 = 35967576152264915259 bsl 2. +8991894038066228814 = 35967576152264915259 bsr 2. +-9425177621947 = -9425177618185 + -3762. +-9425177614423 = -9425177618185 - -3762. +35457518199611970 = -9425177618185 * -3762. +9425177618185 = -(-9425177618185). +-9425177618185 = +(-9425177618185). +2505363534 = -9425177618185 div -3762. +-3277 = -9425177618185 rem -3762. +-9425177620410 = -9425177618185 band -3762. +-1537 = -9425177618185 bor -3762. +9425177618873 = -9425177618185 bxor -3762. +9425177618184 = bnot(-9425177618185). +-1 = -9425177618185 bsl -74. +-178036571516839993116237002482647040 = -9425177618185 bsr -74. +7498725127338 = 7498725127332 + 6. +7498725127326 = 7498725127332 - 6. +44992350763992 = 7498725127332 * 6. +-7498725127332 = -(7498725127332). +7498725127332 = +(7498725127332). +1249787521222 = 7498725127332 div 6. +0 = 7498725127332 rem 6. +4 = 7498725127332 band 6. +7498725127334 = 7498725127332 bor 6. +7498725127330 = 7498725127332 bxor 6. +-7498725127333 = bnot(7498725127332). +0 = 7498725127332 bsl -638. +8553122025330921140993595282243144990572367479830507462601522123573495966844348731535465006154186485117158657367833571146441807249102545221406114737060457937917228945748790915862864350301737636832538001408 = 7498725127332 bsr -638. +8974004074 = -43849548455 + 52823552529. +-96673100984 = -43849548455 - 52823552529. +-2316288926185623292695 = -43849548455 * 52823552529. +43849548455 = -(-43849548455). +-43849548455 = +(-43849548455). +0 = -43849548455 div 52823552529. +-43849548455 = -43849548455 rem 52823552529. +18388119569 = -43849548455 band 52823552529. +-9414115495 = -43849548455 bor 52823552529. +-27802235064 = -43849548455 bxor 52823552529. +43849548454 = bnot(-43849548455). +-171287299 = -43849548455 bsl -8. +-11225484404480 = -43849548455 bsr -8. +-2696151341480155039610 = -2696668659469524633754 + 517317989369594144. +-2697185977458894227898 = -2696668659469524633754 - 517317989369594144. +-1395035208912773235167847251805223136576 = -2696668659469524633754 * 517317989369594144. +2696668659469524633754 = -(-2696668659469524633754). +-2696668659469524633754 = +(-2696668659469524633754). +-5212 = -2696668659469524633754 div 517317989369594144. +-407298875199955226 = -2696668659469524633754 rem 517317989369594144. +10205393930699040 = -2696668659469524633754 band 517317989369594144. +-2696161546874085738650 = -2696668659469524633754 bor 517317989369594144. +-2696171752268016437690 = -2696668659469524633754 bxor 517317989369594144. +2696668659469524633753 = bnot(-2696668659469524633754). +-46328414802279076042559230836736 = -2696668659469524633754 bsl 34. +-156966774927 = -2696668659469524633754 bsr 34. +-337159831121812558591892981637 = -213354536394912 + -337159831121812345237356586725. +337159831121812131882820191813 = -213354536394912 - -337159831121812345237356586725. +71934579459981095625165181309631098976743200 = -213354536394912 * -337159831121812345237356586725. +213354536394912 = -(-213354536394912). +-213354536394912 = +(-213354536394912). +0 = -213354536394912 div -337159831121812345237356586725. +-213354536394912 = -213354536394912 rem -337159831121812345237356586725. +-337159831121812415620346210048 = -213354536394912 band -337159831121812345237356586725. +-142971546771589 = -213354536394912 bor -337159831121812345237356586725. +337159831121812272648799438459 = -213354536394912 bxor -337159831121812345237356586725. +213354536394911 = bnot(-213354536394912). +-1876686348839708223074205696 = -213354536394912 bsl 43. +-25 = -213354536394912 bsr 43. +296274581723538294441 = 296274581723538337699 + -43258. +296274581723538380957 = 296274581723538337699 - -43258. +-12816245856196821412183342 = 296274581723538337699 * -43258. +-296274581723538337699 = -(296274581723538337699). +296274581723538337699 = +(296274581723538337699). +-6849012476849099 = 296274581723538337699 div -43258. +13157 = 296274581723538337699 rem -43258. +296274581723538327298 = 296274581723538337699 band -43258. +-32857 = 296274581723538337699 bor -43258. +-296274581723538360155 = 296274581723538337699 bxor -43258. +-296274581723538337700 = bnot(296274581723538337699). +4629290339430286526 = 296274581723538337699 bsl -6. +18961573230306453612736 = 296274581723538337699 bsr -6. +-2795179228387527847137412139 = 73811352538545589 + -2795179228461339199675957728. +2795179228535150552214503317 = 73811352538545589 - -2795179228461339199675957728. +-206315959440379770010957884816805519764861792 = 73811352538545589 * -2795179228461339199675957728. +-73811352538545589 = -(73811352538545589). +73811352538545589 = +(73811352538545589). +0 = 73811352538545589 div -2795179228461339199675957728. +73811352538545589 = 73811352538545589 rem -2795179228461339199675957728. +591574440442912 = 73811352538545589 band -2795179228461339199675957728. +-2795179228388119421577855051 = 73811352538545589 bor -2795179228461339199675957728. +-2795179228388710996018297963 = 73811352538545589 bxor -2795179228461339199675957728. +-73811352538545590 = bnot(73811352538545589). +21951745852486365331390533787549643026759044079118398227826506135038082976341265195515789437916237414977760255060471755358280849338222559163449801749157628373115303872545583140012311157645083351087974141647608316563146738157835625890058188866567715570838242838777132323892260829840559655555770559234048 = 73811352538545589 bsl 945. +0 = 73811352538545589 bsr 945. +3856978036337648058739 = 3856981361636182577366 + -3325298534518627. +3856984686934717095993 = 3856981361636182577366 - -3325298534518627. +-12825614469514456438512789842995596482 = 3856981361636182577366 * -3325298534518627. +-3856981361636182577366 = -(3856981361636182577366). +3856981361636182577366 = +(3856981361636182577366). +-1159890 = 3856981361636182577366 div -3325298534518627. +844433372306336 = 3856981361636182577366 rem -3325298534518627. +3856978458830441795732 = 3856981361636182577366 band -3325298534518627. +-422492793736993 = 3856981361636182577366 bor -3325298534518627. +-3856978881323235532725 = 3856981361636182577366 bxor -3325298534518627. +-3856981361636182577367 = bnot(3856981361636182577366). +30132666887782676385 = 3856981361636182577366 bsl -7. +493693614289431369902848 = 3856981361636182577366 bsr -7. +-661321514381874695658958184 = -99198762598991 + -661321514381775496896359193. +661321514381676298133760202 = -99198762598991 - -661321514381775496896359193. +65602275906762959875107760914366155374263 = -99198762598991 * -661321514381775496896359193. +99198762598991 = -(-99198762598991). +-99198762598991 = +(-99198762598991). +0 = -99198762598991 div -661321514381775496896359193. +-99198762598991 = -99198762598991 rem -661321514381775496896359193. +-661321514381854730469895007 = -99198762598991 band -661321514381775496896359193. +-19965189063177 = -99198762598991 bor -661321514381775496896359193. +661321514381834765280831830 = -99198762598991 bxor -661321514381775496896359193. +99198762598990 = bnot(-99198762598991). +-843011706507761063802353817455684884896075820720354110340744260908722957174197815508162477953706034861601895234230996573606424974614263170204716079184952542065012482111122397761684618867382385901568 = -99198762598991 bsl 611. +-1 = -99198762598991 bsr 611. +-79187846614272646 = -72626285391 + -79187773987987255. +79187701361701864 = -72626285391 - -79187773987987255. +5751113873129568587300691705 = -72626285391 * -79187773987987255. +72626285391 = -(-72626285391). +-72626285391 = +(-72626285391). +0 = -72626285391 div -79187773987987255. +-72626285391 = -72626285391 rem -79187773987987255. +-79187776282541951 = -72626285391 band -79187773987987255. +-70331730695 = -72626285391 bor -79187773987987255. +79187705950811256 = -72626285391 bxor -79187773987987255. +72626285390 = bnot(-72626285391). +-1162020566256 = -72626285391 bsl 4. +-4539142837 = -72626285391 bsr 4. +654631766685886951274 = 266748 + 654631766685886684526. +-654631766685886417778 = 266748 - 654631766685886684526. +174621714499926901323941448 = 266748 * 654631766685886684526. +-266748 = -(266748). +266748 = +(266748). +0 = 266748 div 654631766685886684526. +266748 = 266748 rem 654631766685886684526. +4460 = 266748 band 654631766685886684526. +654631766685886946814 = 266748 bor 654631766685886684526. +654631766685886942354 = 266748 bxor 654631766685886684526. +-266749 = bnot(266748). +4167 = 266748 bsl -6. +17071872 = 266748 bsr -6. +3194331913276412233660393 = 36414377791915 + 3194331913239997855868478. +-3194331913203583478076563 = 36414377791915 - 3194331913239997855868478. +116319609081491930476239322338291755370 = 36414377791915 * 3194331913239997855868478. +-36414377791915 = -(36414377791915). +36414377791915 = +(36414377791915). +0 = 36414377791915 div 3194331913239997855868478. +36414377791915 = 36414377791915 rem 3194331913239997855868478. +1185411792938 = 36414377791915 band 3194331913239997855868478. +3194331913275226821867455 = 36414377791915 bor 3194331913239997855868478. +3194331913274041410074517 = 36414377791915 bxor 3194331913239997855868478. +-36414377791916 = bnot(36414377791915). +0 = 36414377791915 bsl -243. +514709092139009613858501395657339641731606256350238568349145338242232949900516335288320 = 36414377791915 bsr -243. +6339132293665891298 = 6339132293665891257 + 41. +6339132293665891216 = 6339132293665891257 - 41. +259904424040301541537 = 6339132293665891257 * 41. +-6339132293665891257 = -(6339132293665891257). +6339132293665891257 = +(6339132293665891257). +154612982772338811 = 6339132293665891257 div 41. +6 = 6339132293665891257 rem 41. +41 = 6339132293665891257 band 41. +6339132293665891257 = 6339132293665891257 bor 41. +6339132293665891216 = 6339132293665891257 bxor 41. +-6339132293665891258 = bnot(6339132293665891257). +6540876802517922337097795615425271354928844298415014190466702337110754307535259672876481376235273683129339522762233785446355493168525251329916155541611588867156042761429400960498727161711020718201875316876620233162795732755392651208565655320924567661735650320962331384548650016829341696 = 6339132293665891257 bsl 887. +0 = 6339132293665891257 bsr 887. +383295354711715984308705 = -42155431778539617 + 383295396867147762848322. +-383295439022579541387939 = -42155431778539617 - 383295396867147762848322. +-16157982953661315158369020707121438972674 = -42155431778539617 * 383295396867147762848322. +42155431778539617 = -(-42155431778539617). +-42155431778539617 = +(-42155431778539617). +0 = -42155431778539617 div 383295396867147762848322. +-42155431778539617 = -42155431778539617 rem 383295396867147762848322. +383295395389385881420290 = -42155431778539617 band 383295396867147762848322. +-40677669897111585 = -42155431778539617 bor 383295396867147762848322. +-383295436067055778531875 = -42155431778539617 bxor 383295396867147762848322. +42155431778539616 = bnot(-42155431778539617). +-1414501569043646637932544 = -42155431778539617 bsl 25. +-1256329769 = -42155431778539617 bsr 25. +48709579420901383 = -23944221635562 + 48733523642536945. +-48757467864172507 = -23944221635562 - 48733523642536945. +-1166886291178805365042910838090 = -23944221635562 * 48733523642536945. +23944221635562 = -(-23944221635562). +-23944221635562 = +(-23944221635562). +0 = -23944221635562 div 48733523642536945. +-23944221635562 = -23944221635562 rem 48733523642536945. +48732696319148048 = -23944221635562 band 48733523642536945. +-23116898246665 = -23944221635562 bor 48733523642536945. +-48755813217394713 = -23944221635562 bxor 48733523642536945. +23944221635561 = bnot(-23944221635562). +-187064231528 = -23944221635562 bsl -7. +-3064860369351936 = -23944221635562 bsr -7. +-433297913832315274130561120 = 7923238216626 + -433297913832323197368777746. +433297913832331120606994372 = 7923238216626 - -433297913832323197368777746. +-3433122590060582667514644803870396004996 = 7923238216626 * -433297913832323197368777746. +-7923238216626 = -(7923238216626). +7923238216626 = +(7923238216626). +0 = 7923238216626 div -433297913832323197368777746. +7923238216626 = 7923238216626 rem -433297913832323197368777746. +7698800182178 = 7923238216626 band -433297913832323197368777746. +-433297913832322972930743298 = 7923238216626 bor -433297913832323197368777746. +-433297913832330671730925476 = 7923238216626 bxor -433297913832323197368777746. +-7923238216627 = bnot(7923238216626). +0 = 7923238216626 bsl -88. +2452123457289354197191493662153749037056 = 7923238216626 bsr -88. +473357648279047 = -9836574172179 + 483194222451226. +-493030796623405 = -9836574172179 - 483194222451226. +-4752975808709843967153641454 = -9836574172179 * 483194222451226. +9836574172179 = -(-9836574172179). +-9836574172179 = +(-9836574172179). +0 = -9836574172179 div 483194222451226. +-9836574172179 = -9836574172179 rem 483194222451226. +482703497271816 = -9836574172179 band 483194222451226. +-9345848992769 = -9836574172179 bor 483194222451226. +-492049346264585 = -9836574172179 bxor 483194222451226. +9836574172178 = bnot(-9836574172179). +-1 = -9836574172179 bsl -828. +-17606793912749172550843427523076589979264544829358355822456798783172507525100432953497835342733207977676835352380503993144327689305889086352246266155981325126663410035213905986199732431751681161072054055564182178329935567160742995579258415951996305623912099610624 = -9836574172179 bsr -828. +952179116216 = 4474585 + 952174641631. +-952170167046 = 4474585 - 952174641631. +4260586368822448135 = 4474585 * 952174641631. +-4474585 = -(4474585). +4474585 = +(4474585). +0 = 4474585 div 952174641631. +4474585 = 4474585 rem 952174641631. +217 = 4474585 band 952174641631. +952179115999 = 4474585 bor 952174641631. +952179115782 = 4474585 bxor 952174641631. +-4474586 = bnot(4474585). +34957 = 4474585 bsl -7. +572746880 = 4474585 bsr -7. +6360004 = 91 + 6359913. +-6359822 = 91 - 6359913. +578752083 = 91 * 6359913. +-91 = -(91). +91 = +(91). +0 = 91 div 6359913. +91 = 91 rem 6359913. +73 = 91 band 6359913. +6359931 = 91 bor 6359913. +6359858 = 91 bxor 6359913. +-92 = bnot(91). +5 = 91 bsl -4. +1456 = 91 bsr -4. +4766 = -9 + 4775. +-4784 = -9 - 4775. +-42975 = -9 * 4775. +9 = -(-9). +-9 = +(-9). +0 = -9 div 4775. +-9 = -9 rem 4775. +4775 = -9 band 4775. +-9 = -9 bor 4775. +-4784 = -9 bxor 4775. +8 = bnot(-9). +-1 = -9 bsl -274. +-273187812969243150598049330647057346246588461741707120176036120119533415106982445056 = -9 bsr -274. +965284315779889295267486240 = 965284315779953794811369987 + -64499543883747. +965284315780018294355253734 = 965284315779953794811369987 - -64499543883747. +-62260398085941826544035961668579732901289 = 965284315779953794811369987 * -64499543883747. +-965284315779953794811369987 = -(965284315779953794811369987). +965284315779953794811369987 = +(965284315779953794811369987). +-14965754138041 = 965284315779953794811369987 div -64499543883747. +10057317050360 = 965284315779953794811369987 rem -64499543883747. +965284315779951418077151233 = 965284315779953794811369987 band -64499543883747. +-62122809664993 = 965284315779953794811369987 bor -64499543883747. +-965284315780013540886816226 = 965284315779953794811369987 bxor -64499543883747. +-965284315779953794811369988 = bnot(965284315779953794811369987). +4380475155801998892845301196571361280019643826879041496383329462320530168980671956908579027196908153533698762167225859842996267500189793598273681761756447031851518995847141414482166450061962739401970301137712309293255063821878024688218282842638050668650497046538763680360490864062383649123060113105846534144 = 965284315779953794811369987 bsl 929. +0 = 965284315779953794811369987 bsr 929. +-9566681586293604325086935 = -9566681586787938453518878 + 494334128431943. +-9566681587282272581950821 = -9566681586787938453518878 - 494334128431943. +-4729137204190733020979865587096688719954 = -9566681586787938453518878 * 494334128431943. +9566681586787938453518878 = -(-9566681586787938453518878). +-9566681586787938453518878 = +(-9566681586787938453518878). +-19352662574 = -9566681586787938453518878 div 494334128431943. +-432165851317596 = -9566681586787938453518878 rem 494334128431943. +494334128423234 = -9566681586787938453518878 band 494334128431943. +-9566681586787938453510169 = -9566681586787938453518878 bor 494334128431943. +-9566681587282272581933403 = -9566681586787938453518878 bxor 494334128431943. +9566681586787938453518877 = bnot(-9566681586787938453518878). +-153066905388607015256302048 = -9566681586787938453518878 bsl 4. +-597917599174246153344930 = -9566681586787938453518878 bsr 4. +48668267991694166982 = 48668267991782878894 + -88711912. +48668267991871590806 = 48668267991782878894 - -88711912. +-4317455107279459475551185328 = 48668267991782878894 * -88711912. +-48668267991782878894 = -(48668267991782878894). +48668267991782878894 = +(48668267991782878894). +-548610292513 = 48668267991782878894 div -88711912. +75364038 = 48668267991782878894 rem -88711912. +48668267991765502984 = 48668267991782878894 band -88711912. +-71336002 = 48668267991782878894 bor -88711912. +-48668267991836838986 = 48668267991782878894 bxor -88711912. +-48668267991782878895 = bnot(48668267991782878894). +6083533498972859861 = 48668267991782878894 bsl -3. +389346143934263031152 = 48668267991782878894 bsr -3. +25782325836398723569174 = 56476212692 + 25782325836342247356482. +-25782325836285771143790 = 56476212692 - 25782325836342247356482. +1456088117627711545009952176869544 = 56476212692 * 25782325836342247356482. +-56476212692 = -(56476212692). +56476212692 = +(56476212692). +0 = 56476212692 div 25782325836342247356482. +56476212692 = 56476212692 rem 25782325836342247356482. +38690920512 = 56476212692 band 25782325836342247356482. +25782325836360032648662 = 56476212692 bor 25782325836342247356482. +25782325836321341728150 = 56476212692 bxor 25782325836342247356482. +-56476212693 = bnot(56476212692). +3529763293 = 56476212692 bsl -4. +903619403072 = 56476212692 bsr -4. +544126888057471 = 59572428437918 + 484554459619553. +-424982031181635 = 59572428437918 - 484554459619553. +28866085869959848332359410654 = 59572428437918 * 484554459619553. +-59572428437918 = -(59572428437918). +59572428437918 = +(59572428437918). +0 = 59572428437918 div 484554459619553. +59572428437918 = 59572428437918 rem 484554459619553. +52922593321088 = 59572428437918 band 484554459619553. +491204294736383 = 59572428437918 bor 484554459619553. +438281701415295 = 59572428437918 bxor 484554459619553. +-59572428437919 = bnot(59572428437918). +920879540142378034005739088998035113353252370667466073858283381752546665759251813181966234183165163005062487859289803948100779213626721216453025126753265034957176202865336813677264764928 = 59572428437918 bsl 572. +0 = 59572428437918 bsr 572. +-41927729416296284512550 = -41927729416296284513545 + 995. +-41927729416296284514540 = -41927729416296284513545 - 995. +-41718090769214803090977275 = -41927729416296284513545 * 995. +41927729416296284513545 = -(-41927729416296284513545). +-41927729416296284513545 = +(-41927729416296284513545). +-42138421523915863832 = -41927729416296284513545 div 995. +-705 = -41927729416296284513545 rem 995. +739 = -41927729416296284513545 band 995. +-41927729416296284513289 = -41927729416296284513545 bor 995. +-41927729416296284514028 = -41927729416296284513545 bxor 995. +41927729416296284513544 = bnot(-41927729416296284513545). +-10481932354074071128387 = -41927729416296284513545 bsl -2. +-167710917665185138054180 = -41927729416296284513545 bsr -2. +-369624136911445327 = -3858 + -369624136911441469. +369624136911437611 = -3858 - -369624136911441469. +1426009920204341187402 = -3858 * -369624136911441469. +3858 = -(-3858). +-3858 = +(-3858). +0 = -3858 div -369624136911441469. +-3858 = -3858 rem -369624136911441469. +-369624136911441726 = -3858 band -369624136911441469. +-3601 = -3858 bor -369624136911441469. +369624136911438125 = -3858 bxor -369624136911441469. +3857 = bnot(-3858). +-8 = -3858 bsl -9. +-1975296 = -3858 bsr -9. +-31967719691456702 = -36927457 + -31967719654529245. +31967719617601788 = -36927457 - -31967719654529245. +1180486592930683549979965 = -36927457 * -31967719654529245. +36927457 = -(-36927457). +-36927457 = +(-36927457). +0 = -36927457 div -31967719654529245. +-36927457 = -36927457 rem -31967719654529245. +-31967719657832445 = -36927457 band -31967719654529245. +-33624257 = -36927457 bor -31967719654529245. +31967719624208188 = -36927457 bxor -31967719654529245. +36927456 = bnot(-36927457). +-48300888692627902203159381368269173925083523002745591981120571759374314593897558949114155183332909821880923825185557097902569365832709524017917692999614979130075339638477474642603071212430748615690802283865575088373754619400438658556406320794723029719741519942422027023311439600814151120859653113743671296 = -36927457 bsl 987. +-1 = -36927457 bsr 987. +-47994771759541 = -265696 + -47994771493845. +47994771228149 = -265696 - -47994771493845. +12752018806828641120 = -265696 * -47994771493845. +265696 = -(-265696). +-265696 = +(-265696). +0 = -265696 div -47994771493845. +-265696 = -265696 rem -47994771493845. +-47994771496928 = -265696 band -47994771493845. +-262613 = -265696 bor -47994771493845. +47994771234315 = -265696 bxor -47994771493845. +265695 = bnot(-265696). +-4251136 = -265696 bsl 4. +-16606 = -265696 bsr 4. +-9199171888129156 = -9194377219277887 + -4794668851269. +-9189582550426618 = -9194377219277887 - -4794668851269. +44083994060088968983983588603 = -9194377219277887 * -4794668851269. +9194377219277887 = -(-9194377219277887). +-9194377219277887 = +(-9194377219277887). +1917 = -9194377219277887 div -4794668851269. +-2997031395214 = -9194377219277887 rem -4794668851269. +-9199050555303039 = -9194377219277887 band -4794668851269. +-121332826117 = -9194377219277887 bor -4794668851269. +9198929222476922 = -9194377219277887 bxor -4794668851269. +9194377219277886 = bnot(-9194377219277887). +-2913814450185593058043228609701771773244080128 = -9194377219277887 bsl 98. +-1 = -9194377219277887 bsr 98. +39784597364028809470 = 39874589917552972417 + -89992553524162947. +39964582471077135364 = 39874589917552972417 - -89992553524162947. +-3588416167409434062145463651704432899 = 39874589917552972417 * -89992553524162947. +-39874589917552972417 = -(39874589917552972417). +39874589917552972417 = +(39874589917552972417). +-443 = 39874589917552972417 div -89992553524162947. +7888706348786896 = 39874589917552972417 rem -89992553524162947. +39793806323820397057 = 39874589917552972417 band -89992553524162947. +-9208959791587587 = 39874589917552972417 bor -89992553524162947. +-39803015283611984644 = 39874589917552972417 bxor -89992553524162947. +-39874589917552972418 = bnot(39874589917552972417). +44177613724782317629726103087440850907624966483292366382746735726976564189959417102355828270623805771784678778871474506348138709591737092478985716719593842928610997636257349819585597367194459440485450001490045881291799831376541790352579216953353874488253428812593792225588439865380516445525377024 = 39874589917552972417 bsl 917. +0 = 39874589917552972417 bsr 917. +-44416525916238423771346329 = 371862112393 + -44416525916238795633458722. +44416525916239167495571115 = 371862112393 - -44416525916238795633458722. +-16516823152370988325676184911690141746 = 371862112393 * -44416525916238795633458722. +-371862112393 = -(371862112393). +371862112393 = +(371862112393). +0 = 371862112393 div -44416525916238795633458722. +371862112393 = 371862112393 rem -44416525916238795633458722. +354343190664 = 371862112393 band -44416525916238795633458722. +-44416525916238778114536993 = 371862112393 bor -44416525916238795633458722. +-44416525916239132457727657 = 371862112393 bxor -44416525916238795633458722. +-371862112394 = bnot(371862112393). +0 = 371862112393 bsl -72. +1756069175813808117623456454934528 = 371862112393 bsr -72. +-3865686417158761331434189 = -863 + -3865686417158761331433326. +3865686417158761331432463 = -863 - -3865686417158761331433326. +3336087378008011029026960338 = -863 * -3865686417158761331433326. +863 = -(-863). +-863 = +(-863). +0 = -863 div -3865686417158761331433326. +-863 = -863 rem -3865686417158761331433326. +-3865686417158761331433344 = -863 band -3865686417158761331433326. +-845 = -863 bor -3865686417158761331433326. +3865686417158761331432499 = -863 bxor -3865686417158761331433326. +862 = bnot(-863). +-4 = -863 bsl -8. +-220928 = -863 bsr -8. +727539561357448124806725677 = 727539561357448124539998794 + 266726883. +727539561357448124273271911 = 727539561357448124539998794 - 266726883. +194054359460059387092749687147379102 = 727539561357448124539998794 * 266726883. +-727539561357448124539998794 = -(727539561357448124539998794). +727539561357448124539998794 = +(727539561357448124539998794). +2727657419358993238 = 727539561357448124539998794 div 266726883. +150181640 = 727539561357448124539998794 rem 266726883. +213909570 = 727539561357448124539998794 band 266726883. +727539561357448124592816107 = 727539561357448124539998794 bor 266726883. +727539561357448124378906537 = 727539561357448124539998794 bxor 266726883. +-727539561357448124539998795 = bnot(727539561357448124539998794). +0 = 727539561357448124539998794 bsl -793. +37900346059551112482395129926244905271818313722396862075761608118559495567606489509093257379637005489271882584535403108973651072452029113565088475423250923853072711617314417667217591005076220972638849002500670093256802323450051418911175916633384168603386087995342848 = 727539561357448124539998794 bsr -793. +4845615483639054675854643916 = -97549726517766 + 4845615483639152225581161682. +-4845615483639249775307679448 = -97549726517766 - 4845615483639152225581161682. +-472688465239251728979641804071054891442412 = -97549726517766 * 4845615483639152225581161682. +97549726517766 = -(-97549726517766). +-97549726517766 = +(-97549726517766). +0 = -97549726517766 div 4845615483639152225581161682. +-97549726517766 = -97549726517766 rem 4845615483639152225581161682. +4845615483639064090704499922 = -97549726517766 band 4845615483639152225581161682. +-9414849856006 = -97549726517766 bor 4845615483639152225581161682. +-4845615483639073505554355928 = -97549726517766 bxor 4845615483639152225581161682. +97549726517765 = bnot(-97549726517766). +-390198906071064 = -97549726517766 bsl 2. +-24387431629442 = -97549726517766 bsr 2. +6639170004 = 6639178221 + -8217. +6639186438 = 6639178221 - -8217. +-54554127441957 = 6639178221 * -8217. +-6639178221 = -(6639178221). +6639178221 = +(6639178221). +-807980 = 6639178221 div -8217. +6561 = 6639178221 rem -8217. +6639178213 = 6639178221 band -8217. +-8209 = 6639178221 bor -8217. +-6639186422 = 6639178221 bxor -8217. +-6639178222 = bnot(6639178221). +53113425768 = 6639178221 bsl 3. +829897277 = 6639178221 bsr 3. +33481279823977461794349784 = 33481277286797878946675326 + 2537179582847674458. +33481274749618296099000868 = 33481277286797878946675326 - 2537179582847674458. +84948013139725160201646406502066349869023308 = 33481277286797878946675326 * 2537179582847674458. +-33481277286797878946675326 = -(33481277286797878946675326). +33481277286797878946675326 = +(33481277286797878946675326). +13196258 = 33481277286797878946675326 div 2537179582847674458. +919207592098897162 = 33481277286797878946675326 rem 2537179582847674458. +2391556963994576986 = 33481277286797878946675326 band 2537179582847674458. +33481277432420497799772798 = 33481277286797878946675326 bor 2537179582847674458. +33481275040863533805195812 = 33481277286797878946675326 bxor 2537179582847674458. +-33481277286797878946675327 = bnot(33481277286797878946675326). +2470482213481859956052584333671314613562507264 = 33481277286797878946675326 bsl 66. +453755 = 33481277286797878946675326 bsr 66. +2949630 = 2949658 + -28. +2949686 = 2949658 - -28. +-82590424 = 2949658 * -28. +-2949658 = -(2949658). +2949658 = +(2949658). +-105344 = 2949658 div -28. +26 = 2949658 rem -28. +2949632 = 2949658 band -28. +-2 = 2949658 bor -28. +-2949634 = 2949658 bxor -28. +-2949659 = bnot(2949658). +204247949655482574992198843144245417155122976000711607807759657083365083062948847360093802222986870853603096865933994972242869949257164051767014234801443625572032584030766673239601613500109640599284135073096453005744860671238600929503948062015275568879262681196614132524091845902336 = 2949658 bsl 913. +0 = 2949658 bsr 913. +54213750915990011984673215 = 681915667814577758327862 + 53531835248175434226345353. +-52849919580360856468017491 = 681915667814577758327862 - 53531835248175434226345353. +36504197182599504119108093734255607396776614125286 = 681915667814577758327862 * 53531835248175434226345353. +-681915667814577758327862 = -(681915667814577758327862). +681915667814577758327862 = +(681915667814577758327862). +0 = 681915667814577758327862 div 53531835248175434226345353. +681915667814577758327862 = 681915667814577758327862 rem 53531835248175434226345353. +1302260960919421977600 = 681915667814577758327862 band 53531835248175434226345353. +54212448655029092562695615 = 681915667814577758327862 bor 53531835248175434226345353. +54211146394068173140718015 = 681915667814577758327862 bxor 53531835248175434226345353. +-681915667814577758327863 = bnot(681915667814577758327862). +1610127846915616446784725449733263096310398976 = 681915667814577758327862 bsl 71. +288 = 681915667814577758327862 bsr 71. +6851766981 = -52815 + 6851819796. +-6851872611 = -52815 - 6851819796. +-361878862525740 = -52815 * 6851819796. +52815 = -(-52815). +-52815 = +(-52815). +0 = -52815 div 6851819796. +-52815 = -52815 rem 6851819796. +6851801360 = -52815 band 6851819796. +-34379 = -52815 bor 6851819796. +-6851835739 = -52815 bxor 6851819796. +52814 = bnot(-52815). +-1 = -52815 bsl -47. +-7433050447486648320 = -52815 bsr -47. +-66628139849827523346014 = -66628139849827523391548 + 45534. +-66628139849827523437082 = -66628139849827523391548 - 45534. +-3033845719922046450110746632 = -66628139849827523391548 * 45534. +66628139849827523391548 = -(-66628139849827523391548). +-66628139849827523391548 = +(-66628139849827523391548). +-1463261295950883370 = -66628139849827523391548 div 45534. +-21968 = -66628139849827523391548 rem 45534. +33220 = -66628139849827523391548 band 45534. +-66628139849827523379234 = -66628139849827523391548 bor 45534. +-66628139849827523412454 = -66628139849827523391548 bxor 45534. +66628139849827523391547 = bnot(-66628139849827523391548). +-1 = -66628139849827523391548 bsl -837. +-61061020653629541530678333423590394702630673329368349208169542556834451981708470066769456666195053957164684750814833252120673860604316558971076065384053138153960634900506615586342480493979509916032696769423700469570953563285507702655565472021062634858074372881152933841862656 = -66628139849827523391548 bsr -837. +9211374728442040 = 8224434745967512 + 986939982474528. +7237494763492984 = 8224434745967512 - 986939982474528. +8117023484048075436999255534336 = 8224434745967512 * 986939982474528. +-8224434745967512 = -(8224434745967512). +8224434745967512 = +(8224434745967512). +8 = 8224434745967512 div 986939982474528. +328914886171288 = 8224434745967512 rem 986939982474528. +281562201522432 = 8224434745967512 band 986939982474528. +8929812526919608 = 8224434745967512 bor 986939982474528. +8648250325397176 = 8224434745967512 bxor 986939982474528. +-8224434745967513 = bnot(8224434745967512). +1939919231042380565962104015342735378726303987800599269510469133672945844084547228682084943200234731603251107588955360021639289241623954321289129635876931859117892133750335247044575232 = 8224434745967512 bsl 556. +0 = 8224434745967512 bsr 556. +-5483258629748897366 = 8354925 + -5483258629757252291. +5483258629765607216 = 8354925 - -5483258629757252291. +-45812214607224611097383175 = 8354925 * -5483258629757252291. +-8354925 = -(8354925). +8354925 = +(8354925). +0 = 8354925 div -5483258629757252291. +8354925 = 8354925 rem -5483258629757252291. +3755053 = 8354925 band -5483258629757252291. +-5483258629752652419 = 8354925 bor -5483258629757252291. +-5483258629756407472 = 8354925 bxor -5483258629757252291. +-8354926 = bnot(8354925). +0 = 8354925 bsl -26. +560689525555200 = 8354925 bsr -26. +4381739694537252289 = 4381739686354483342 + 8182768947. +4381739678171714395 = 4381739686354483342 - 8182768947. +35854763439338985925146380874 = 4381739686354483342 * 8182768947. +-4381739686354483342 = -(4381739686354483342). +4381739686354483342 = +(4381739686354483342). +535483735 = 4381739686354483342 div 8182768947. +7972906297 = 4381739686354483342 rem 8182768947. +6025322498 = 4381739686354483342 band 8182768947. +4381739688511929791 = 4381739686354483342 bor 8182768947. +4381739682486607293 = 4381739686354483342 bxor 8182768947. +-4381739686354483343 = bnot(4381739686354483342). +0 = 4381739686354483342 bsl -893. +289356139145147333863788455805704466017305954143094341143482572359115241899220389383039670575892056266347435138152573334213173358216552878730871724255074771593291995484866587673770807274116435463555953886907273598495937987036797992684062401606201791030148991671207019891702586048316964864 = 4381739686354483342 bsr -893. +79187393169177576755434820123 = -5365966382688351766 + 79187393174543543138123171889. +-79187393179909509520811523655 = -5365966382688351766 - 79187393174543543138123171889. +-424916889707325692610969117094605702893314705974 = -5365966382688351766 * 79187393174543543138123171889. +5365966382688351766 = -(-5365966382688351766). +-5365966382688351766 = +(-5365966382688351766). +0 = -5365966382688351766 div 79187393174543543138123171889. +-5365966382688351766 = -5365966382688351766 rem 79187393174543543138123171889. +79187393173804384522707683360 = -5365966382688351766 band 79187393174543543138123171889. +-4626807767272863237 = -5365966382688351766 bor 79187393174543543138123171889. +-79187393178431192289980546597 = -5365966382688351766 bxor 79187393174543543138123171889. +5365966382688351765 = bnot(-5365966382688351766). +-2747374787936436104192 = -5365966382688351766 bsl 9. +-10480403091188188 = -5365966382688351766 bsr 9. +-5611968923644672949873679 = -5611968923644672949873582 + -97. +-5611968923644672949873485 = -5611968923644672949873582 - -97. +544360985593533276137737454 = -5611968923644672949873582 * -97. +5611968923644672949873582 = -(-5611968923644672949873582). +-5611968923644672949873582 = +(-5611968923644672949873582). +57855349728295597421377 = -5611968923644672949873582 div -97. +-13 = -5611968923644672949873582 rem -97. +-5611968923644672949873646 = -5611968923644672949873582 band -97. +-33 = -5611968923644672949873582 bor -97. +5611968923644672949873613 = -5611968923644672949873582 bxor -97. +5611968923644672949873581 = bnot(-5611968923644672949873582). +-158647853125905587983965055420542576055990822820929885620968234464499599091920176631475980690522112 = -5611968923644672949873582 bsl 244. +-1 = -5611968923644672949873582 bsr 244. +-73539392680305865807 = -73539393618444719756 + 938138853949. +-73539394556583573705 = -73539393618444719756 - 938138853949. +-68990162449312133579704318916444 = -73539393618444719756 * 938138853949. +73539393618444719756 = -(-73539393618444719756). +-73539393618444719756 = +(-73539393618444719756). +-78388602 = -73539393618444719756 div 938138853949. +-375500430458 = -73539393618444719756 rem 938138853949. +1684561972 = -73539393618444719756 band 938138853949. +-73539392681990427779 = -73539393618444719756 bor 938138853949. +-73539392683674989751 = -73539393618444719756 bxor 938138853949. +73539393618444719755 = bnot(-73539393618444719756). +-11112958963017639143168135532523822495301632 = -73539393618444719756 bsl 77. +-1 = -73539393618444719756 bsr 77. +783890351610663724836834062 = 54536735517382498342324 + 783835814875146342338491738. +-783781278139628959840149414 = 54536735517382498342324 - 783835814875146342338491738. +42747846524897846348628188420967043453483369719112 = 54536735517382498342324 * 783835814875146342338491738. +-54536735517382498342324 = -(54536735517382498342324). +54536735517382498342324 = +(54536735517382498342324). +0 = 54536735517382498342324 div 783835814875146342338491738. +54536735517382498342324 = 54536735517382498342324 rem 783835814875146342338491738. +54309592454742337934608 = 54536735517382498342324 band 783835814875146342338491738. +783836042018208982498899454 = 54536735517382498342324 bor 783835814875146342338491738. +783781732425754240160964846 = 54536735517382498342324 bxor 783835814875146342338491738. +-54536735517382498342325 = bnot(54536735517382498342324). +0 = 54536735517382498342324 bsl -548. +50248923489998030034903198320077145750115194695859954245153889712191233506311786196207510945877569332115110911097771254434310271268639802234354416067215336690923897090580052311182927724544 = 54536735517382498342324 bsr -548. +71759253949874661270359909355 = 71759253949874661271235447583 + -875538228. +71759253949874661272110985811 = 71759253949874661271235447583 - -875538228. +-62827970045875261751517711147606702924 = 71759253949874661271235447583 * -875538228. +-71759253949874661271235447583 = -(71759253949874661271235447583). +71759253949874661271235447583 = +(71759253949874661271235447583). +-81960160795942608768 = 71759253949874661271235447583 div -875538228. +803464479 = 71759253949874661271235447583 rem -875538228. +71759253949874661270429386764 = 71759253949874661271235447583 band -875538228. +-69477409 = 71759253949874661271235447583 bor -875538228. +-71759253949874661270498864173 = 71759253949874661271235447583 bxor -875538228. +-71759253949874661271235447584 = bnot(71759253949874661271235447583). +14952866907201716632509004323935665096218601299062227623271212072714077064817014161146843592699415623073129145583197929812711978595091326214835567719882706352747661494762832039731719901097875516322832472336710965583335005123342937603392785017008665065918059346283986944 = 71759253949874661271235447583 bsl 795. +0 = 71759253949874661271235447583 bsr 795. +9114771611346090 = -39233 + 9114771611385323. +-9114771611424556 = -39233 - 9114771611385323. +-357599834629480377259 = -39233 * 9114771611385323. +39233 = -(-39233). +-39233 = +(-39233). +0 = -39233 div 9114771611385323. +-39233 = -39233 rem 9114771611385323. +9114771611346091 = -39233 band 9114771611385323. +-1 = -39233 bor 9114771611385323. +-9114771611346092 = -39233 bxor 9114771611385323. +39232 = bnot(-39233). +-77 = -39233 bsl -9. +-20087296 = -39233 bsr -9. +-92493277314758890 = -92493277314686391 + -72499. +-92493277314613892 = -92493277314686391 - -72499. +6705670112037448661109 = -92493277314686391 * -72499. +92493277314686391 = -(-92493277314686391). +-92493277314686391 = +(-92493277314686391). +1275786939332 = -92493277314686391 div -72499. +-55723 = -92493277314686391 rem -72499. +-92493277314752439 = -92493277314686391 band -72499. +-6451 = -92493277314686391 bor -72499. +92493277314745988 = -92493277314686391 bxor -72499. +92493277314686390 = bnot(-92493277314686391). +-5919569748139929024 = -92493277314686391 bsl 6. +-1445207458041975 = -92493277314686391 bsr 6. +64821233361388145113497646784 = 562 + 64821233361388145113497646222. +-64821233361388145113497645660 = 562 - 64821233361388145113497646222. +36429533149100137553785677176764 = 562 * 64821233361388145113497646222. +-562 = -(562). +562 = +(562). +0 = 562 div 64821233361388145113497646222. +562 = 562 rem 64821233361388145113497646222. +2 = 562 band 64821233361388145113497646222. +64821233361388145113497646782 = 562 bor 64821233361388145113497646222. +64821233361388145113497646780 = 562 bxor 64821233361388145113497646222. +-563 = bnot(562). +0 = 562 bsl -298. +286203554674995295120716619221517631627731309310064043214377733134290572616748807218767331328 = 562 bsr -298. +-214404149705 = -214397688214 + -6461491. +-214391226723 = -214397688214 - -6461491. +1385328732815567074 = -214397688214 * -6461491. +214397688214 = -(-214397688214). +-214397688214 = +(-214397688214). +33180 = -214397688214 div -6461491. +-5416834 = -214397688214 rem -6461491. +-214404143544 = -214397688214 band -6461491. +-6161 = -214397688214 bor -6461491. +214404137383 = -214397688214 bxor -6461491. +214397688213 = bnot(-214397688214). +-26799711027 = -214397688214 bsl -3. +-1715181505712 = -214397688214 bsr -3. +-7935720450961869732011057 = -222425217168495549558481 + -7713295233793374182452576. +7490870016624878632894095 = -222425217168495549558481 - -7713295233793374182452576. +1715631367461212905019038579907922366374521097056 = -222425217168495549558481 * -7713295233793374182452576. +222425217168495549558481 = -(-222425217168495549558481). +-222425217168495549558481 = +(-222425217168495549558481). +0 = -222425217168495549558481 div -7713295233793374182452576. +-222425217168495549558481 = -222425217168495549558481 rem -7713295233793374182452576. +-7779429221288574896254944 = -222425217168495549558481 band -7713295233793374182452576. +-156291229673294835756113 = -222425217168495549558481 bor -7713295233793374182452576. +7623137991615280060498831 = -222425217168495549558481 bxor -7713295233793374182452576. +222425217168495549558480 = bnot(-222425217168495549558481). +-1 = -222425217168495549558481 bsl -288. +-110617228861385846832181611898216202123399104524737012955318627588625390123827573845641751515474090468820647936 = -222425217168495549558481 bsr -288. +939060 = 936531 + 2529. +934002 = 936531 - 2529. +2368486899 = 936531 * 2529. +-936531 = -(936531). +936531 = +(936531). +370 = 936531 div 2529. +801 = 936531 rem 2529. +2113 = 936531 band 2529. +936947 = 936531 bor 2529. +934834 = 936531 bxor 2529. +-936532 = bnot(936531). +0 = 936531 bsl -69. +552830325571048962703491072 = 936531 bsr -69. +-2852442502912101042364 = -2852942484288572612327 + 499981376471569963. +-2853442465665044182290 = -2852942484288572612327 - 499981376471569963. +-1426418110288820897544258290069856733901 = -2852942484288572612327 * 499981376471569963. +2852942484288572612327 = -(-2852942484288572612327). +-2852942484288572612327 = +(-2852942484288572612327). +-5706 = -2852942484288572612327 div 499981376471569963. +-48750141794403449 = -2852942484288572612327 rem 499981376471569963. +463872967389347849 = -2852942484288572612327 band 499981376471569963. +-2852906375879490390213 = -2852942484288572612327 bor 499981376471569963. +-2853370248846879738062 = -2852942484288572612327 bxor 499981376471569963. +2852942484288572612326 = bnot(-2852942484288572612327). +-730353275977874588755712 = -2852942484288572612327 bsl 8. +-11144306579252236767 = -2852942484288572612327 bsr 8. +-4551914114467152301 = 3681681323 + -4551914118148833624. +4551914121830514947 = 3681681323 - -4551914118148833624. +-16758697192688576087715204552 = 3681681323 * -4551914118148833624. +-3681681323 = -(3681681323). +3681681323 = +(3681681323). +0 = 3681681323 div -4551914118148833624. +3681681323 = 3681681323 rem -4551914118148833624. +52510376 = 3681681323 band -4551914118148833624. +-4551914114519662677 = 3681681323 bor -4551914118148833624. +-4551914114572173053 = 3681681323 bxor -4551914118148833624. +-3681681324 = bnot(3681681323). +7190783 = 3681681323 bsl -9. +1885020837376 = 3681681323 bsr -9. +-89182662169448522409091 = -89182662164652578816278 + -4795943592813. +-89182662159856635223465 = -89182662164652578816278 - -4795943592813. +427715017198571888620065965968210014 = -89182662164652578816278 * -4795943592813. +89182662164652578816278 = -(-89182662164652578816278). +-89182662164652578816278 = +(-89182662164652578816278). +18595436005 = -89182662164652578816278 div -4795943592813. +-908659384213 = -89182662164652578816278 rem -4795943592813. +-89182662169170959917950 = -89182662164652578816278 band -4795943592813. +-277562491141 = -89182662164652578816278 bor -4795943592813. +89182662168893397426809 = -89182662164652578816278 bxor -4795943592813. +89182662164652578816277 = bnot(-89182662164652578816278). +-1393479096322696544005 = -89182662164652578816278 bsl -6. +-5707690378537765044241792 = -89182662164652578816278 bsr -6. +632545389415606345 = 9131421835176 + 632536257993771169. +-632527126571935993 = 9131421835176 - 632536257993771169. +5775955397784841728006978840744 = 9131421835176 * 632536257993771169. +-9131421835176 = -(9131421835176). +9131421835176 = +(9131421835176). +0 = 9131421835176 div 632536257993771169. +9131421835176 = 9131421835176 rem 632536257993771169. +9071256537248 = 9131421835176 band 632536257993771169. +632536318159069097 = 9131421835176 bor 632536257993771169. +632527246902531849 = 9131421835176 bxor 632536257993771169. +-9131421835177 = bnot(9131421835176). +4966446146660946458439123605341255292009634626855273740252574599074841436823948039774841525780525323097117652732871837238747964247145232892143144668276764293363353532420323977978151928168918047260672 = 9131421835176 bsl 617. +0 = 9131421835176 bsr 617. +628467798272410 = 617 + 628467798271793. +-628467798271176 = 617 - 628467798271793. +387764631533696281 = 617 * 628467798271793. +-617 = -(617). +617 = +(617). +0 = 617 div 628467798271793. +617 = 617 rem 628467798271793. +545 = 617 band 628467798271793. +628467798271865 = 617 bor 628467798271793. +628467798271320 = 617 bxor 628467798271793. +-618 = bnot(617). +44459535521401536512 = 617 bsl 56. +0 = 617 bsr 56. +3349939166095985147910546 = 3349938368558747723283131 + 797537237424627415. +3349937571021510298655716 = 3349938368558747723283131 - 797537237424627415. +2671700592003107001257687187823898229636365 = 3349938368558747723283131 * 797537237424627415. +-3349938368558747723283131 = -(3349938368558747723283131). +3349938368558747723283131 = +(3349938368558747723283131). +4200353 = 3349938368558747723283131 div 797537237424627415. +440730501686805636 = 3349938368558747723283131 rem 797537237424627415. +76853680943405715 = 3349938368558747723283131 band 797537237424627415. +3349939089242304204504831 = 3349938368558747723283131 bor 797537237424627415. +3349939012388623261099116 = 3349938368558747723283131 bxor 797537237424627415. +-3349938368558747723283132 = bnot(3349938368558747723283131). +0 = 3349938368558747723283131 bsl -85. +129594463611788089464584360769616723420831434145792 = 3349938368558747723283131 bsr -85. +6386447 = 6779 + 6379668. +-6372889 = 6779 - 6379668. +43247769372 = 6779 * 6379668. +-6779 = -(6779). +6779 = +(6779). +0 = 6779 div 6379668. +6779 = 6779 rem 6379668. +6160 = 6779 band 6379668. +6380287 = 6779 bor 6379668. +6374127 = 6779 bxor 6379668. +-6780 = bnot(6779). +3581308626568674705022511401949066075591266023198867798505445646491822385432037822377074577662428076737997723659290075314143434105868705257021403735000267391861953330829255465579830958328494843898451274884763646191719483796562837027585492576741740274122582039905765890719744 = 6779 bsl 896. +0 = 6779 bsr 896. +-416640072 = -7576 + -416632496. +416624920 = -7576 - -416632496. +3156407789696 = -7576 * -416632496. +7576 = -(-7576). +-7576 = +(-7576). +0 = -7576 div -416632496. +-7576 = -7576 rem -416632496. +-416636864 = -7576 band -416632496. +-3208 = -7576 bor -416632496. +416633656 = -7576 bxor -416632496. +7575 = bnot(-7576). +-18122040996845715967928180977059971505791224602120730723781423931381466355085051103893937433367232236603569150272235755161925780488396639187638504473606485280134063274303615014969202379566754146275033088 = -7576 bsl 659. +-1 = -7576 bsr 659. +95447279398571924885740904 = -541 + 95447279398571924885741445. +-95447279398571924885741986 = -541 - 95447279398571924885741445. +-51636978154627411363186121745 = -541 * 95447279398571924885741445. +541 = -(-541). +-541 = +(-541). +0 = -541 div 95447279398571924885741445. +-541 = -541 rem 95447279398571924885741445. +95447279398571924885740929 = -541 band 95447279398571924885741445. +-25 = -541 bor 95447279398571924885741445. +-95447279398571924885740954 = -541 bxor 95447279398571924885741445. +540 = bnot(-541). +-1 = -541 bsl -76. +-40876804275719648969752576 = -541 bsr -76. +-56166218967 = -99819836458 + 43653617491. +-143473453949 = -99819836458 - 43653617491. +-4357496958751708286878 = -99819836458 * 43653617491. +99819836458 = -(-99819836458). +-99819836458 = +(-99819836458). +-2 = -99819836458 div 43653617491. +-12512601476 = -99819836458 rem 43653617491. +34364195666 = -99819836458 band 43653617491. +-90530414633 = -99819836458 bor 43653617491. +-124894610299 = -99819836458 bxor 43653617491. +99819836457 = bnot(-99819836458). +-1 = -99819836458 bsl -584. +-6320250937891014880117158995322339818026510986708959014357773064574126455177221787777628770828395108621203423478412972882583915910031223087169043632598445656991544468013674755319270473728 = -99819836458 bsr -584. +-39394918556145756519903048269 = -39394918556145756519934536445 + 31488176. +-39394918556145756519966024621 = -39394918556145756519934536445 - 31488176. +-1240474129001583462952846192058574320 = -39394918556145756519934536445 * 31488176. +39394918556145756519934536445 = -(-39394918556145756519934536445). +-39394918556145756519934536445 = +(-39394918556145756519934536445). +-1251101955100408372969 = -39394918556145756519934536445 div 31488176. +-13021901 = -39394918556145756519934536445 rem 31488176. +10506240 = -39394918556145756519934536445 band 31488176. +-39394918556145756519913554509 = -39394918556145756519934536445 bor 31488176. +-39394918556145756519924060749 = -39394918556145756519934536445 bxor 31488176. +39394918556145756519934536444 = bnot(-39394918556145756519934536445). +-1 = -39394918556145756519934536445 bsl -733. +-1780028798475663899313794956801320316158277918977430074417848601707585154174768737231872948239599259481202593635313473975351259309647662557576980403048292705610626819624592707960493930346520749099995844854314387825837143542701975430418076519565885440 = -39394918556145756519934536445 bsr -733. +-942218636829645973571 = 9541594 + -942218636829655515165. +942218636829665056759 = 9541594 - -942218636829655515165. +-8990267691862020085565273010 = 9541594 * -942218636829655515165. +-9541594 = -(9541594). +9541594 = +(9541594). +0 = 9541594 div -942218636829655515165. +9541594 = 9541594 rem -942218636829655515165. +9476034 = 9541594 band -942218636829655515165. +-942218636829655449605 = 9541594 bor -942218636829655515165. +-942218636829664925639 = 9541594 bxor -942218636829655515165. +-9541595 = bnot(9541594). +0 = 9541594 bsl -53. +85943038365841120821248 = 9541594 bsr -53. +359263544344378002 = 22525 + 359263544344355477. +-359263544344332952 = 22525 - 359263544344355477. +8092411336356607119425 = 22525 * 359263544344355477. +-22525 = -(22525). +22525 = +(22525). +0 = 22525 div 359263544344355477. +22525 = 22525 rem 359263544344355477. +661 = 22525 band 359263544344355477. +359263544344377341 = 22525 bor 359263544344355477. +359263544344376680 = 22525 bxor 359263544344355477. +-22526 = bnot(22525). +90100 = 22525 bsl 2. +5631 = 22525 bsr 2. +-3326662191 = -3326662578 + 387. +-3326662965 = -3326662578 - 387. +-1287418417686 = -3326662578 * 387. +3326662578 = -(-3326662578). +-3326662578 = +(-3326662578). +-8596027 = -3326662578 div 387. +-129 = -3326662578 rem 387. +2 = -3326662578 band 387. +-3326662193 = -3326662578 bor 387. +-3326662195 = -3326662578 bxor 387. +3326662577 = bnot(-3326662578). +-446497093041782784 = -3326662578 bsl 27. +-25 = -3326662578 bsr 27. +9122678121848255133767059 = 9122678121848255133774381 + -7322. +9122678121848255133781703 = 9122678121848255133774381 - -7322. +-66796249208172924089496017682 = 9122678121848255133774381 * -7322. +-9122678121848255133774381 = -(9122678121848255133774381). +9122678121848255133774381 = +(9122678121848255133774381). +-1245927085748191086284 = 9122678121848255133774381 div -7322. +2933 = 9122678121848255133774381 rem -7322. +9122678121848255133770276 = 9122678121848255133774381 band -7322. +-3217 = 9122678121848255133774381 bor -7322. +-9122678121848255133773493 = 9122678121848255133774381 bxor -7322. +-9122678121848255133774382 = bnot(9122678121848255133774381). +71270922826939493232612 = 9122678121848255133774381 bsl -7. +1167702799596576657123120768 = 9122678121848255133774381 bsr -7. +-93467851987533385442390274598 = -6998279695768832496435489362 + -86469572291764552945954785236. +79471292595995720449519295874 = -6998279695768832496435489362 - -86469572291764552945954785236. +605138252071271103733214166260700576672786898959272659432 = -6998279695768832496435489362 * -86469572291764552945954785236. +6998279695768832496435489362 = -(-6998279695768832496435489362). +-6998279695768832496435489362 = +(-6998279695768832496435489362). +0 = -6998279695768832496435489362 div -86469572291764552945954785236. +-6998279695768832496435489362 = -6998279695768832496435489362 rem -86469572291764552945954785236. +-86653344739603769203471773652 = -6998279695768832496435489362 band -86469572291764552945954785236. +-6814507247929616238918500946 = -6998279695768832496435489362 bor -86469572291764552945954785236. +79838837491674152964553272706 = -6998279695768832496435489362 bxor -86469572291764552945954785236. +6998279695768832496435489361 = bnot(-6998279695768832496435489362). +-437392480985552031027218086 = -6998279695768832496435489362 bsl -4. +-111972475132301319942967829792 = -6998279695768832496435489362 bsr -4. +-47887784345477057051 = -47887784399154513386 + 53677456335. +-47887784452831969721 = -47887784399154513386 - 53677456335. +-2570494456065510603195188000310 = -47887784399154513386 * 53677456335. +47887784399154513386 = -(-47887784399154513386). +-47887784399154513386 = +(-47887784399154513386). +-892139599 = -47887784399154513386 div 53677456335. +-29107603721 = -47887784399154513386 rem 53677456335. +52334754310 = -47887784399154513386 band 53677456335. +-47887784397811811361 = -47887784399154513386 bor 53677456335. +-47887784450146565671 = -47887784399154513386 bxor 53677456335. +47887784399154513385 = bnot(-47887784399154513386). +-21776844 = -47887784399154513386 bsl -41. +-105306351550601034262356082819072 = -47887784399154513386 bsr -41. +-79316814638770194316947865550 = -46945142255491325454964751682 + -32371672383278868861983113868. +-14573469872212456592981637814 = -46945142255491325454964751682 - -32371672383278868861983113868. +1519692765081186408722971619574264846511184431031750525976 = -46945142255491325454964751682 * -32371672383278868861983113868. +46945142255491325454964751682 = -(-46945142255491325454964751682). +-46945142255491325454964751682 = +(-46945142255491325454964751682). +1 = -46945142255491325454964751682 div -32371672383278868861983113868. +-14573469872212456592981637814 = -46945142255491325454964751682 rem -32371672383278868861983113868. +-79142615909218722686232428492 = -46945142255491325454964751682 band -32371672383278868861983113868. +-174198729551471630715437058 = -46945142255491325454964751682 bor -32371672383278868861983113868. +78968417179667251055516991434 = -46945142255491325454964751682 bxor -32371672383278868861983113868. +46945142255491325454964751681 = bnot(-46945142255491325454964751682). +-1467035695484103920467648491 = -46945142255491325454964751682 bsl -5. +-1502244552175722414558872053824 = -46945142255491325454964751682 bsr -5. +-959256731475517667191147619 = -959256731475517597311251448 + -69879896171. +-959256731475517527431355277 = -959256731475517597311251448 - -69879896171. +67032760796841997328593639956313405608 = -959256731475517597311251448 * -69879896171. +959256731475517597311251448 = -(-959256731475517597311251448). +-959256731475517597311251448 = +(-959256731475517597311251448). +13727220331412097 = -959256731475517597311251448 div -69879896171. +-49137870861 = -959256731475517597311251448 rem -69879896171. +-959256731475517666097871872 = -959256731475517597311251448 band -69879896171. +-1093275747 = -959256731475517597311251448 bor -69879896171. +959256731475517665004596125 = -959256731475517597311251448 bxor -69879896171. +959256731475517597311251447 = bnot(-959256731475517597311251448). +-74218894740472983230499719574570888012122512290742272 = -959256731475517597311251448 bsl 86. +-13 = -959256731475517597311251448 bsr 86. +-7636256537005201989969009000 = -7735619899564627144133283782 + 99363362559425154164274782. +-7834983262124052298297558564 = -7735619899564627144133283782 - 99363362559425154164274782. +-768637204702344044187714998374778579284830200232185524 = -7735619899564627144133283782 * 99363362559425154164274782. +7735619899564627144133283782 = -(-7735619899564627144133283782). +-7735619899564627144133283782 = +(-7735619899564627144133283782). +-77 = -7735619899564627144133283782 div 99363362559425154164274782. +-84640982488890273484125568 = -7735619899564627144133283782 rem 99363362559425154164274782. +226685510059814126366746 = -7735619899564627144133283782 band 99363362559425154164274782. +-7636483222515261804095375746 = -7735619899564627144133283782 bor 99363362559425154164274782. +-7636709908025321618221742492 = -7735619899564627144133283782 bxor 99363362559425154164274782. +7735619899564627144133283781 = bnot(-7735619899564627144133283782). +-1 = -7735619899564627144133283782 bsl -952. +-294476738258171150599617898367824151666477449653244545539179271066059551908021445021373336676213218319522988394235273605055872991465124045264656669368839068869654064706291126766925685578764235202272405610013145652686307873063005905912788538570286021969964306150351272383224523163385128550321369284951279666695503872 = -7735619899564627144133283782 bsr -952. +5189354565971672 = 4398231646349891 + 791122919621781. +3607108726728110 = 4398231646349891 - 791122919621781. +3479541861233238334550910575871 = 4398231646349891 * 791122919621781. +-4398231646349891 = -(4398231646349891). +4398231646349891 = +(4398231646349891). +5 = 4398231646349891 div 791122919621781. +442617048240986 = 4398231646349891 rem 791122919621781. +703691879940097 = 4398231646349891 band 791122919621781. +4485662686031575 = 4398231646349891 bor 791122919621781. +3781970806091478 = 4398231646349891 bxor 791122919621781. +-4398231646349892 = bnot(4398231646349891). +0 = 4398231646349891 bsl -57. +633851980914895752036374598909952 = 4398231646349891 bsr -57. +-66462493333953656144175 = -66462493333953656144148 + -27. +-66462493333953656144121 = -66462493333953656144148 - -27. +1794487320016748715891996 = -66462493333953656144148 * -27. +66462493333953656144148 = -(-66462493333953656144148). +-66462493333953656144148 = +(-66462493333953656144148). +2461573827183468746079 = -66462493333953656144148 div -27. +-15 = -66462493333953656144148 rem -27. +-66462493333953656144156 = -66462493333953656144148 band -27. +-19 = -66462493333953656144148 bor -27. +66462493333953656144137 = -66462493333953656144148 bxor -27. +66462493333953656144147 = bnot(-66462493333953656144148). +-531699946671629249153184 = -66462493333953656144148 bsl 3. +-8307811666744207018019 = -66462493333953656144148 bsr 3. +-95484272407718148579925639801 = -5163374558913331895812 + -95484267244343589666593743989. +95484262080969030753261848177 = -5163374558913331895812 - -95484267244343589666593743989. +493021036265925287117377824018467509063892349274068 = -5163374558913331895812 * -95484267244343589666593743989. +5163374558913331895812 = -(-5163374558913331895812). +-5163374558913331895812 = +(-5163374558913331895812). +0 = -5163374558913331895812 div -95484267244343589666593743989. +-5163374558913331895812 = -5163374558913331895812 rem -95484267244343589666593743989. +-95484272054337006900938718840 = -5163374558913331895812 band -95484267244343589666593743989. +-353381141678986920961 = -5163374558913331895812 bor -95484267244343589666593743989. +95484271700955865221951797879 = -5163374558913331895812 bxor -95484267244343589666593743989. +5163374558913331895811 = bnot(-5163374558913331895812). +-80677727483020810873 = -5163374558913331895812 bsl -6. +-330455971770453241331968 = -5163374558913331895812 bsr -6. +-728291976857434384373484660277 = -6136 + -728291976857434384373484654141. +728291976857434384373484648005 = -6136 - -728291976857434384373484654141. +4468799569997217382515701837809176 = -6136 * -728291976857434384373484654141. +6136 = -(-6136). +-6136 = +(-6136). +0 = -6136 div -728291976857434384373484654141. +-6136 = -6136 rem -728291976857434384373484654141. +-728291976857434384373484658688 = -6136 band -728291976857434384373484654141. +-1589 = -6136 bor -728291976857434384373484654141. +728291976857434384373484657099 = -6136 bxor -728291976857434384373484654141. +6135 = bnot(-6136). +-196352 = -6136 bsl 5. +-192 = -6136 bsr 5. +-255897171117657553338 = 7 + -255897171117657553345. +255897171117657553352 = 7 - -255897171117657553345. +-1791280197823602873415 = 7 * -255897171117657553345. +-7 = -(7). +7 = +(7). +0 = 7 div -255897171117657553345. +7 = 7 rem -255897171117657553345. +7 = 7 band -255897171117657553345. +-255897171117657553345 = 7 bor -255897171117657553345. +-255897171117657553352 = 7 bxor -255897171117657553345. +-8 = bnot(7). +3584 = 7 bsl 9. +0 = 7 bsr 9. +327659896220292618768682756 = 61713382968829984 + 327659896158579235799852772. +-327659896096865852831022788 = 61713382968829984 - 327659896158579235799852772. +20221000655161464908942372144898492299115648 = 61713382968829984 * 327659896158579235799852772. +-61713382968829984 = -(61713382968829984). +61713382968829984 = +(61713382968829984). +0 = 61713382968829984 div 327659896158579235799852772. +61713382968829984 = 61713382968829984 rem 327659896158579235799852772. +52399225577504 = 61713382968829984 band 327659896158579235799852772. +327659896220240219543105252 = 61713382968829984 bor 327659896158579235799852772. +327659896220187820317527748 = 61713382968829984 bxor 327659896158579235799852772. +-61713382968829985 = bnot(61713382968829984). +2673606666864789640199890437071214500263506125978353728418541999859694514267787931734957644905255199855096668552593175655049499727010700453740544 = 61713382968829984 bsl 424. +0 = 61713382968829984 bsr 424. +-41468119058294390 = -535695115 + -41468118522599275. +41468117986904160 = -535695115 - -41468118522599275. +22214268520797448720041625 = -535695115 * -41468118522599275. +535695115 = -(-535695115). +-535695115 = +(-535695115). +0 = -535695115 div -41468118522599275. +-535695115 = -535695115 rem -41468118522599275. +-41468118621429611 = -535695115 band -41468118522599275. +-436864779 = -535695115 bor -41468118522599275. +41468118184564832 = -535695115 bxor -41468118522599275. +535695114 = bnot(-535695115). +-555718804966498486056123639866735224318786187703107235755854288182306793058727785492506975888007348999538127502749434140163481607696271161478154955312821425111515949552269758866058180034560 = -535695115 bsl 598. +-1 = -535695115 bsr 598. +-7687388271331556624628222776 = 567539817 + -7687388271331556625195762593. +7687388271331556625763302410 = 567539817 - -7687388271331556625195762593. +-4362898932719457993388740691206665481 = 567539817 * -7687388271331556625195762593. +-567539817 = -(567539817). +567539817 = +(567539817). +0 = 567539817 div -7687388271331556625195762593. +567539817 = 567539817 rem -7687388271331556625195762593. +29587529 = 567539817 band -7687388271331556625195762593. +-7687388271331556624657810305 = 567539817 bor -7687388271331556625195762593. +-7687388271331556624687397834 = 567539817 bxor -7687388271331556625195762593. +-567539818 = bnot(567539817). +0 = 567539817 bsl -895. +149914090761418128044033419526669597570583809234739872029132135692094377387859729432730742794061566488239060704529433522179169649225275380409858787494111834380321602201016086825595741332105663784597330220645777832121347009089521887862272784249805703749598764308570959644779872256 = 567539817 bsr -895. +-271876793993788 = 47 + -271876793993835. +271876793993882 = 47 - -271876793993835. +-12778209317710245 = 47 * -271876793993835. +-47 = -(47). +47 = +(47). +0 = 47 div -271876793993835. +47 = 47 rem -271876793993835. +5 = 47 band -271876793993835. +-271876793993793 = 47 bor -271876793993835. +-271876793993798 = 47 bxor -271876793993835. +-48 = bnot(47). +0 = 47 bsl -7. +6016 = 47 bsr -7. +2957935961678274511090515 = -628899 + 2957935961678274511719414. +-2957935961678274512348313 = -628899 - 2957935961678274511719414. +-1860242968363505162145827745186 = -628899 * 2957935961678274511719414. +628899 = -(-628899). +-628899 = +(-628899). +0 = -628899 div 2957935961678274511719414. +-628899 = -628899 rem 2957935961678274511719414. +2957935961678274511651668 = -628899 band 2957935961678274511719414. +-561153 = -628899 bor 2957935961678274511719414. +-2957935961678274512212821 = -628899 bxor 2957935961678274511719414. +628898 = bnot(-628899). +-1 = -628899 bsl -262. +-4660577864272570751084055609662644259904872965519147845366453447999523796315271069696 = -628899 bsr -262. +-2134739549478317544367 = 417825184917526139286 + -2552564734395843683653. +2970389919313369822939 = 417825184917526139286 - -2552564734395843683653. +-1066525832162899381985364983898885799291758 = 417825184917526139286 * -2552564734395843683653. +-417825184917526139286 = -(417825184917526139286). +417825184917526139286 = +(417825184917526139286). +0 = 417825184917526139286 div -2552564734395843683653. +417825184917526139286 = 417825184917526139286 rem -2552564734395843683653. +380467502953848819858 = 417825184917526139286 band -2552564734395843683653. +-2515207052432166364225 = 417825184917526139286 bor -2552564734395843683653. +-2895674555386015184083 = 417825184917526139286 bxor -2552564734395843683653. +-417825184917526139287 = bnot(417825184917526139286). +0 = 417825184917526139286 bsl -586. +105821051628775302540019449117422307372788400977033737301827098767360059441259056456375975687517232564538623450082399539570963500720198873199082481060631384759042571813704318479195354072313709461504 = 417825184917526139286 bsr -586. +65348459157074999199412310 = 65348459156717665282542516 + 357333916869794. +65348459156360331365672722 = 65348459156717665282542516 - 357333916869794. +23351220871875678725546248635536441161704 = 65348459156717665282542516 * 357333916869794. +-65348459156717665282542516 = -(65348459156717665282542516). +65348459156717665282542516 = +(65348459156717665282542516). +182877851979 = 65348459156717665282542516 div 357333916869794. +327187134320190 = 65348459156717665282542516 rem 357333916869794. +343617061024 = 65348459156717665282542516 band 357333916869794. +65348459157074655582351286 = 65348459156717665282542516 bor 357333916869794. +65348459157074311965290262 = 65348459156717665282542516 bxor 357333916869794. +-65348459156717665282542517 = bnot(65348459156717665282542516). +963369646005615849436861831463875639304554151636736647798813648922317577483620894478811593879355376037264307609013532944946246538408084699742556180761937401506292607357517926271625814853287936 = 65348459156717665282542516 bsl 552. +0 = 65348459156717665282542516 bsr 552. +82983973517509960 = 82983973517475534 + 34426. +82983973517441108 = 82983973517475534 - 34426. +2856806272312612733484 = 82983973517475534 * 34426. +-82983973517475534 = -(82983973517475534). +82983973517475534 = +(82983973517475534). +2410502919812 = 82983973517475534 div 34426. +27622 = 82983973517475534 rem 34426. +1610 = 82983973517475534 band 34426. +82983973517508350 = 82983973517475534 bor 34426. +82983973517506740 = 82983973517475534 bxor 34426. +-82983973517475535 = bnot(82983973517475534). +104071373546698694201735881906791178166996828921478528184482511645647327574232864181745195351097946190811926743969178466711406403669731970037407822299028809439676023308953516811124116217612698305359897905687757289995370496 = 82983973517475534 bsl 678. +0 = 82983973517475534 bsr 678. +-63745812445273723555466583743 = -63745812445273723555466625664 + 41921. +-63745812445273723555466667585 = -63745812445273723555466625664 - 41921. +-2672288203518319765168716414460544 = -63745812445273723555466625664 * 41921. +63745812445273723555466625664 = -(-63745812445273723555466625664). +-63745812445273723555466625664 = +(-63745812445273723555466625664). +-1520617648559760586709921 = -63745812445273723555466625664 div 41921. +-27423 = -63745812445273723555466625664 rem 41921. +8576 = -63745812445273723555466625664 band 41921. +-63745812445273723555466592319 = -63745812445273723555466625664 bor 41921. +-63745812445273723555466600895 = -63745812445273723555466625664 bxor 41921. +63745812445273723555466625663 = bnot(-63745812445273723555466625664). +-6592 = -63745812445273723555466625664 bsl -83. +-616511668459223720181482832961376249103493771047206912 = -63745812445273723555466625664 bsr -83. +-31346355498113217 = -64 + -31346355498113153. +31346355498113089 = -64 - -31346355498113153. +2006166751879241792 = -64 * -31346355498113153. +64 = -(-64). +-64 = +(-64). +0 = -64 div -31346355498113153. +-64 = -64 rem -31346355498113153. +-31346355498113216 = -64 band -31346355498113153. +-1 = -64 bor -31346355498113153. +31346355498113215 = -64 bxor -31346355498113153. +63 = bnot(-64). +-645562469521727147413979793000752968582426448207305878207664839135161905504210298657411338320034457858975792993186873344 = -64 bsl 392. +-1 = -64 bsr 392. +-6149421864998047819362004 = 345328854531 + -6149421864998393148216535. +6149421864998738477071066 = 345328854531 - -6149421864998393148216535. +-2123572808667780828029214937103870085 = 345328854531 * -6149421864998393148216535. +-345328854531 = -(345328854531). +345328854531 = +(345328854531). +0 = 345328854531 div -6149421864998393148216535. +345328854531 = 345328854531 rem -6149421864998393148216535. +344201372161 = 345328854531 band -6149421864998393148216535. +-6149421864998392020734165 = 345328854531 bor -6149421864998393148216535. +-6149421864998736222106326 = 345328854531 bxor -6149421864998393148216535. +-345328854532 = bnot(345328854531). +1236229985648790720140825348929489781677170882473230453855854197366391334552042905720116564304224528376972518078198688469362639253242806828985118145108745184426782194439105078579460863521995194467044977426616924637733277133789922549224835456258032541070390198272 = 345328854531 bsl 829. +0 = 345328854531 bsr 829. +-45456559819945214994526 = 518218891 + -45456559819945733213417. +45456559819946251432308 = 518218891 - -45456559819945733213417. +-23556448018567437546038824060547 = 518218891 * -45456559819945733213417. +-518218891 = -(518218891). +518218891 = +(518218891). +0 = 518218891 div -45456559819945733213417. +518218891 = 518218891 rem -45456559819945733213417. +136323075 = 518218891 band -45456559819945733213417. +-45456559819945351317601 = 518218891 bor -45456559819945733213417. +-45456559819945487640676 = 518218891 bxor -45456559819945733213417. +-518218892 = bnot(518218891). +2024292 = 518218891 bsl -8. +132664036096 = 518218891 bsr -8. +981107618657309 = -833879618242 + 981941498275551. +-982775377893793 = -833879618242 - 981941498275551. +-818821001717993969202201342 = -833879618242 * 981941498275551. +833879618242 = -(-833879618242). +-833879618242 = +(-833879618242). +0 = -833879618242 div 981941498275551. +-833879618242 = -833879618242 rem 981941498275551. +981932873663518 = -833879618242 band 981941498275551. +-825255006209 = -833879618242 bor 981941498275551. +-982758128669727 = -833879618242 bxor 981941498275551. +833879618241 = bnot(-833879618242). +-928839414178366905934203589000236592058142035897290206229403095403923419980586576125314662445572910144126809670971212444331872797646975882602165499109003875192023740319959678259052811936697283459940352 = -833879618242 bsl 628. +-1 = -833879618242 bsr 628. +91739893931159218326346947398 = 941 + 91739893931159218326346946457. +-91739893931159218326346945516 = 941 - 91739893931159218326346946457. +86327240189220824445092476616037 = 941 * 91739893931159218326346946457. +-941 = -(941). +941 = +(941). +0 = 941 div 91739893931159218326346946457. +941 = 941 rem 91739893931159218326346946457. +905 = 941 band 91739893931159218326346946457. +91739893931159218326346946493 = 941 bor 91739893931159218326346946457. +91739893931159218326346945588 = 941 bxor 91739893931159218326346946457. +-942 = bnot(941). +252597764096 = 941 bsl 28. +0 = 941 bsr 28. +-9456264219673416 = -9456264219274591 + -398825. +-9456264218875766 = -9456264219274591 - -398825. +3771394577252188755575 = -9456264219274591 * -398825. +9456264219274591 = -(-9456264219274591). +-9456264219274591 = +(-9456264219274591). +23710309582 = -9456264219274591 div -398825. +-233441 = -9456264219274591 rem -398825. +-9456264219672063 = -9456264219274591 band -398825. +-1353 = -9456264219274591 bor -398825. +9456264219670710 = -9456264219274591 bxor -398825. +9456264219274590 = bnot(-9456264219274591). +-634599149439364706074624 = -9456264219274591 bsl 26. +-140909318 = -9456264219274591 bsr 26. +6865215386180237197481 = 353463884 + 6865215386179883733597. +-6865215386179530269713 = 353463884 - 6865215386179883733597. +2426605694895701627145616910748 = 353463884 * 6865215386179883733597. +-353463884 = -(353463884). +353463884 = +(353463884). +0 = 353463884 div 6865215386179883733597. +353463884 = 353463884 rem 6865215386179883733597. +335610444 = 353463884 band 6865215386179883733597. +6865215386179901587037 = 353463884 bor 6865215386179883733597. +6865215386179565976593 = 353463884 bxor 6865215386179883733597. +-353463885 = bnot(353463884). +178082501288577240848078587402645659914638037742368543155041634761774079512727259778196069624589135450143236703554934037709754321498623217036440075322058651839594907283944119630839112845539422125720019636017744203172611037538391169810880104228736423635165207073176078516224 = 353463884 bsl 876. +0 = 353463884 bsr 876. +3734635776523991788537932207 = 84552 + 3734635776523991788537847655. +-3734635776523991788537763103 = 84552 - 3734635776523991788537847655. +315770924176656553704452094925560 = 84552 * 3734635776523991788537847655. +-84552 = -(84552). +84552 = +(84552). +0 = 84552 div 3734635776523991788537847655. +84552 = 84552 rem 3734635776523991788537847655. +68160 = 84552 band 3734635776523991788537847655. +3734635776523991788537864047 = 84552 bor 3734635776523991788537847655. +3734635776523991788537795887 = 84552 bxor 3734635776523991788537847655. +-84553 = bnot(84552). +660 = 84552 bsl -7. +10822656 = 84552 bsr -7. +2782778678603311 = -39836525 + 2782778718439836. +-2782778758276361 = -39836525 - 2782778718439836. +-110856233986596487809900 = -39836525 * 2782778718439836. +39836525 = -(-39836525). +-39836525 = +(-39836525). +0 = -39836525 div 2782778718439836. +-39836525 = -39836525 rem 2782778718439836. +2782778718421136 = -39836525 band 2782778718439836. +-39817825 = -39836525 bor 2782778718439836. +-2782778758238961 = -39836525 bxor 2782778718439836. +39836524 = bnot(-39836525). +-1 = -39836525 bsl -46. +-2803246236652116377600 = -39836525 bsr -46. +7561228265255773898606129 = 64399986374386 + 7561228265191373912231743. +-7561228265126973925857357 = 64399986374386 - 7561228265191373912231743. +486942997251946772560427191460391334798 = 64399986374386 * 7561228265191373912231743. +-64399986374386 = -(64399986374386). +64399986374386 = +(64399986374386). +0 = 64399986374386 div 7561228265191373912231743. +64399986374386 = 64399986374386 rem 7561228265191373912231743. +2207613781554 = 64399986374386 band 7561228265191373912231743. +7561228265253566284824575 = 64399986374386 bor 7561228265191373912231743. +7561228265251358671043021 = 64399986374386 bxor 7561228265191373912231743. +-64399986374387 = bnot(64399986374386). +155709612621651092297023693430164815872 = 64399986374386 bsl 81. +0 = 64399986374386 bsr 81. +-293768271718296280472 = -293768271719154417444 + 858136972. +-293768271720012554416 = -293768271719154417444 - 858136972. +-252093415162748406185818139568 = -293768271719154417444 * 858136972. +293768271719154417444 = -(-293768271719154417444). +-293768271719154417444 = +(-293768271719154417444). +-342332612746 = -293768271719154417444 div 858136972. +-453372332 = -293768271719154417444 rem 858136972. +50725004 = -293768271719154417444 band 858136972. +-293768271718347005476 = -293768271719154417444 bor 858136972. +-293768271718397730480 = -293768271719154417444 bxor 858136972. +293768271719154417443 = bnot(-293768271719154417444). +-75204677560103530865664 = -293768271719154417444 bsl 8. +-1147532311402946944 = -293768271719154417444 bsr 8. +7334628981256154244320 = 6 + 7334628981256154244314. +-7334628981256154244308 = 6 - 7334628981256154244314. +44007773887536925465884 = 6 * 7334628981256154244314. +-6 = -(6). +6 = +(6). +0 = 6 div 7334628981256154244314. +6 = 6 rem 7334628981256154244314. +2 = 6 band 7334628981256154244314. +7334628981256154244318 = 6 bor 7334628981256154244314. +7334628981256154244316 = 6 bxor 7334628981256154244314. +-7 = bnot(6). +48 = 6 bsl 3. +0 = 6 bsr 3. +-484689735605708013667484 = -484689729221194738721122 + -6384513274946362. +-484689722836681463774760 = -484689729221194738721122 - -6384513274946362. +3094508010442875433029193488499026458164 = -484689729221194738721122 * -6384513274946362. +484689729221194738721122 = -(-484689729221194738721122). +-484689729221194738721122 = +(-484689729221194738721122). +75916472 = -484689729221194738721122 div -6384513274946362. +-5950100946446258 = -484689729221194738721122 rem -6384513274946362. +-484689729226143887483770 = -484689729221194738721122 band -6384513274946362. +-6379564126183714 = -484689729221194738721122 bor -6384513274946362. +484689722846579761300056 = -484689729221194738721122 bxor -6384513274946362. +484689729221194738721121 = bnot(-484689729221194738721122). +-3407152045104124367017271929002010304822004118541879927081529418883046659294496161374843964190705909987297679873244728454802455339323150218637293463093441609411771424703629741634093056 = -484689729221194738721122 bsl 531. +-1 = -484689729221194738721122 bsr 531. +97275658985222212 = -9831226364 + 97275668816448576. +-97275678647674940 = -9831226364 - 97275668816448576. +-956339119844001917221457664 = -9831226364 * 97275668816448576. +9831226364 = -(-9831226364). +-9831226364 = +(-9831226364). +0 = -9831226364 div 97275668816448576. +-9831226364 = -9831226364 rem 97275668816448576. +97275668798325760 = -9831226364 band 97275668816448576. +-9813103548 = -9831226364 bor 97275668816448576. +-97275678611429308 = -9831226364 bxor 97275668816448576. +9831226363 = bnot(-9831226364). +-218069947164034966789202107619672282027864460589294264974753653179697026601398604901956177657410076397815275462605092654470227515792045375488 = -9831226364 bsl 433. +-1 = -9831226364 bsr 433. +811334966792538 = 811334971748727 + -4956189. +811334976704916 = 811334971748727 - -4956189. +-4021129462296351521403 = 811334971748727 * -4956189. +-811334971748727 = -(811334971748727). +811334971748727 = +(811334971748727). +-163701378 = 811334971748727 div -4956189. +2820285 = 811334971748727 rem -4956189. +811334966989155 = 811334971748727 band -4956189. +-196617 = 811334971748727 bor -4956189. +-811334967185772 = 811334971748727 bxor -4956189. +-811334971748728 = bnot(811334971748727). +0 = 811334971748727 bsl -584. +51370957898696338924979062684267574889692713921960031697929223518883541308686122246026955424429435685879870308869332170294114526221878140437663970272288492929969523669597608930525213183967232 = 811334971748727 bsr -584. +9386646838474838885886405 = 9386646838474838878344919 + 7541486. +9386646838474838870803433 = 9386646838474838878344919 - 7541486. +70789265719302258753293909809634 = 9386646838474838878344919 * 7541486. +-9386646838474838878344919 = -(9386646838474838878344919). +9386646838474838878344919 = +(9386646838474838878344919). +1244668071846163856 = 9386646838474838878344919 div 7541486. +4614903 = 9386646838474838878344919 rem 7541486. +135878 = 9386646838474838878344919 band 7541486. +9386646838474838885750527 = 9386646838474838878344919 bor 7541486. +9386646838474838885614649 = 9386646838474838878344919 bxor 7541486. +-9386646838474838878344920 = bnot(9386646838474838878344919). +73333178425584678737069 = 9386646838474838878344919 bsl -7. +1201490795324779376428149632 = 9386646838474838878344919 bsr -7. +-37668595329896688694811341665 = 968955878746223172532899 + -37669564285775434917983874564. +37670533241654181141156407463 = 968955878746223172532899 - -37669564285775434917983874564. +-36500145764510881221050255830505417406356885779281036 = 968955878746223172532899 * -37669564285775434917983874564. +-968955878746223172532899 = -(968955878746223172532899). +968955878746223172532899 = +(968955878746223172532899). +0 = 968955878746223172532899 div -37669564285775434917983874564. +968955878746223172532899 = 968955878746223172532899 rem -37669564285775434917983874564. +326658692321257898512544 = 968955878746223172532899 band -37669564285775434917983874564. +-37668921988589009952709854209 = 968955878746223172532899 bor -37669564285775434917983874564. +-37669248647281331210608366753 = 968955878746223172532899 bxor -37669564285775434917983874564. +-968955878746223172532900 = bnot(968955878746223172532899). +15058883548636265840324379812208556560337747233343885124606900333031925746470989114966905517118570701931937792 = 968955878746223172532899 bsl 283. +0 = 968955878746223172532899 bsr 283. +627532199385515150887717802077 = 5458823246133 + 627532199385515145428894555944. +-627532199385515139970071309811 = 5458823246133 - 627532199385515145428894555944. +3425587357702618774070593756411997650164552 = 5458823246133 * 627532199385515145428894555944. +-5458823246133 = -(5458823246133). +5458823246133 = +(5458823246133). +0 = 5458823246133 div 627532199385515145428894555944. +5458823246133 = 5458823246133 rem 627532199385515145428894555944. +4425430077728 = 5458823246133 band 627532199385515145428894555944. +627532199385515146462287724349 = 5458823246133 bor 627532199385515145428894555944. +627532199385515142036857646621 = 5458823246133 bxor 627532199385515145428894555944. +-5458823246134 = bnot(5458823246133). +2794917502020096 = 5458823246133 bsl 9. +10661764152 = 5458823246133 bsr 9. +-31585827561050681201 = -2338687527 + -31585827558711993674. +31585827556373306147 = -2338687527 - -31585827558711993674. +73869380941532599790686704198 = -2338687527 * -31585827558711993674. +2338687527 = -(-2338687527). +-2338687527 = +(-2338687527). +0 = -2338687527 div -31585827558711993674. +-2338687527 = -2338687527 rem -31585827558711993674. +-31585827558881865584 = -2338687527 band -31585827558711993674. +-2168815617 = -2338687527 bor -31585827558711993674. +31585827556713049967 = -2338687527 bxor -31585827558711993674. +2338687526 = bnot(-2338687527). +-1 = -2338687527 bsl -533. +-65759709852165087769940772575489996288042718555253349062666077449644046015414156042793337269979323586161617517094356159490764375295512553139276209064246923605092528553984 = -2338687527 bsr -533. +5812121546762844266932235 = 5812121546762844267224589 + -292354. +5812121546762844267516943 = 5812121546762844267224589 - -292354. +-1699196982682304572900177492506 = 5812121546762844267224589 * -292354. +-5812121546762844267224589 = -(5812121546762844267224589). +5812121546762844267224589 = +(5812121546762844267224589). +-19880424234875679030 = 5812121546762844267224589 div -292354. +87969 = 5812121546762844267224589 rem -292354. +5812121546762844267218956 = 5812121546762844267224589 band -292354. +-286721 = 5812121546762844267224589 bor -292354. +-5812121546762844267505677 = 5812121546762844267224589 bxor -292354. +-5812121546762844267224590 = bnot(5812121546762844267224589). +615 = 5812121546762844267224589 bsl -73. +54893935973594670110177900039258388459461541888 = 5812121546762844267224589 bsr -73. +3331753125934228494 = -7443 + 3331753125934235937. +-3331753125934243380 = -7443 - 3331753125934235937. +-24798238516328518079091 = -7443 * 3331753125934235937. +7443 = -(-7443). +-7443 = +(-7443). +0 = -7443 div 3331753125934235937. +-7443 = -7443 rem 3331753125934235937. +3331753125934235681 = -7443 band 3331753125934235937. +-7187 = -7443 bor 3331753125934235937. +-3331753125934242868 = -7443 bxor 3331753125934235937. +7442 = bnot(-7443). +-1 = -7443 bsl -798. +-12407507855981188840494084219584580446037109048249326109457336723239932290269158877083504967771744646499906831136730902159687587677902608573286114774374592008271564466080702589660172920510407946514421653774850994637431059410734325347533184827392 = -7443 bsr -798. +26635721247961419918017306131 = 28479837341185584372 + 26635721219481582576831721759. +-26635721191001745235646137387 = 28479837341185584372 - 26635721219481582576831721759. +758581007796000805728711634493377859651322750348 = 28479837341185584372 * 26635721219481582576831721759. +-28479837341185584372 = -(28479837341185584372). +28479837341185584372 = +(28479837341185584372). +0 = 28479837341185584372 div 26635721219481582576831721759. +28479837341185584372 = 28479837341185584372 rem 26635721219481582576831721759. +9804530054297034772 = 28479837341185584372 band 26635721219481582576831721759. +26635721238156889863720271359 = 28479837341185584372 bor 26635721219481582576831721759. +26635721228352359809423236587 = 28479837341185584372 bxor 26635721219481582576831721759. +-28479837341185584373 = bnot(28479837341185584372). +8208754229589487061188871904735264768 = 28479837341185584372 bsl 58. +98 = 28479837341185584372 bsr 58. +784958823981468756737666093662 = 632875826637545 + 784958823981468123861839456117. +-784958823981467490986012818572 = 632875826637545 - 784958823981468123861839456117. +496781464603706821016997050696933563692112765 = 632875826637545 * 784958823981468123861839456117. +-632875826637545 = -(632875826637545). +632875826637545 = +(632875826637545). +0 = 632875826637545 div 784958823981468123861839456117. +632875826637545 = 632875826637545 rem 784958823981468123861839456117. +67620506509921 = 632875826637545 band 784958823981468123861839456117. +784958823981468689117159583741 = 632875826637545 bor 784958823981468123861839456117. +784958823981468621496653073820 = 632875826637545 bxor 784958823981468123861839456117. +-632875826637546 = bnot(632875826637545). +0 = 632875826637545 bsl -593. +20516625748444697013132472763415875732836671730728516550567464549598887302810888413024109757475171676866082875547269136780171543238563532659989925889572073146078421290869696111709877260926320640 = 632875826637545 bsr -593. +-2914193355372640051694253540 = 515622817551199632229525229 + -3429816172923839683923778769. +3945438990475039316153303998 = 515622817551199632229525229 - -3429816172923839683923778769. +-1768491478765662757411666562480603349534105948500063101 = 515622817551199632229525229 * -3429816172923839683923778769. +-515622817551199632229525229 = -(515622817551199632229525229). +515622817551199632229525229 = +(515622817551199632229525229). +0 = 515622817551199632229525229 div -3429816172923839683923778769. +515622817551199632229525229 = 515622817551199632229525229 rem -3429816172923839683923778769. +206122455245401623684473389 = 515622817551199632229525229 band -3429816172923839683923778769. +-3120315810618041675378726929 = 515622817551199632229525229 bor -3429816172923839683923778769. +-3326438265863443299063200318 = 515622817551199632229525229 bxor -3429816172923839683923778769. +-515622817551199632229525230 = bnot(515622817551199632229525229). +0 = 515622817551199632229525229 bsl -276. +62605275486156137647802923481395651866850404438681977171102591552274731760454431062534142921293166485537030144 = 515622817551199632229525229 bsr -276. +-9913453277908 = -3738727 + -9913449539181. +9913445800454 = -3738727 - -9913449539181. +37063681455273562587 = -3738727 * -9913449539181. +3738727 = -(-3738727). +-3738727 = +(-3738727). +0 = -3738727 div -9913449539181. +-3738727 = -3738727 rem -9913449539181. +-9913451114095 = -3738727 band -9913449539181. +-2163813 = -3738727 bor -9913449539181. +9913448950282 = -3738727 bxor -9913449539181. +3738726 = bnot(-3738727). +-934682 = -3738727 bsl -2. +-14954908 = -3738727 bsr -2. +56395812787692 = 56399367924819 + -3555137127. +56402923061946 = 56399367924819 - -3555137127. +-200507486848856971655013 = 56399367924819 * -3555137127. +-56399367924819 = -(56399367924819). +56399367924819 = +(56399367924819). +-15864 = 56399367924819 div -3555137127. +672542091 = 56399367924819 rem -3555137127. +56397216114705 = 56399367924819 band -3555137127. +-1403327013 = 56399367924819 bor -3555137127. +-56398619441718 = 56399367924819 bxor -3555137127. +-56399367924820 = bnot(56399367924819). +0 = 56399367924819 bsl -729. +159272602282009369804829167225421786302420595178138543748234819107412786245682622256854084210389395589458167604383150065493827422572034432629455384375599948907220540068921691169946166324347611732916449742155274846225999064909299580928 = 56399367924819 bsr -729. +4994279985463060 = 3395489689 + 4994276589973371. +-4994273194483682 = 3395489689 - 4994276589973371. +16958014665268662015071619 = 3395489689 * 4994276589973371. +-3395489689 = -(3395489689). +3395489689 = +(3395489689). +0 = 3395489689 div 4994276589973371. +3395489689 = 3395489689 rem 4994276589973371. +2181173017 = 3395489689 band 4994276589973371. +4994277804290043 = 3395489689 bor 4994276589973371. +4994275623117026 = 3395489689 bxor 4994276589973371. +-3395489690 = bnot(3395489689). +0 = 3395489689 bsl -291. +13509247370636319377028265275489356165531332673832186424934247239333258613907867043126852213276672 = 3395489689 bsr -291. +523243201587728280751 = 523242478127831926822 + 723459896353929. +523241754667935572893 = 523242478127831926822 - 723459896353929. +378544948994334247525429156540183638 = 523242478127831926822 * 723459896353929. +-523242478127831926822 = -(523242478127831926822). +523242478127831926822 = +(523242478127831926822). +723250 = 523242478127831926822 div 723459896353929. +108089852777572 = 523242478127831926822 rem 723459896353929. +723038416994304 = 523242478127831926822 band 723459896353929. +523242478549311286447 = 523242478127831926822 bor 723459896353929. +523241755510894292143 = 523242478127831926822 bxor 723459896353929. +-523242478127831926823 = bnot(523242478127831926822). +0 = 523242478127831926822 bsl -999. +2803294094797220652232266501811179882751129680863999088493038299717880199239545298634531365335411847272580723990775872043912169086424045641711796232129861039764268922701116650361817709508239089301422949197285315743815759829635246059669306007739749073740441686438866628351372490944813670278407068149346034570668047425601536 = 523242478127831926822 bsr -999. +4252353997369259107525 = 4252353997362499368692 + 6759738833. +4252353997355739629859 = 4252353997362499368692 - 6759738833. +28744802447634066560485296816436 = 4252353997362499368692 * 6759738833. +-4252353997362499368692 = -(4252353997362499368692). +4252353997362499368692 = +(4252353997362499368692). +629070752941 = 4252353997362499368692 div 6759738833. +2672710839 = 4252353997362499368692 rem 6759738833. +2172112 = 4252353997362499368692 band 6759738833. +4252353997369256935413 = 4252353997362499368692 bor 6759738833. +4252353997369254763301 = 4252353997362499368692 bxor 6759738833. +-4252353997362499368693 = bnot(4252353997362499368692). +33221515604394526317 = 4252353997362499368692 bsl -7. +544301311662399919192576 = 4252353997362499368692 bsr -7. +54472535782100 = 54472535869625 + -87525. +54472535957150 = 54472535869625 - -87525. +-4767708701988928125 = 54472535869625 * -87525. +-54472535869625 = -(54472535869625). +54472535869625 = +(54472535869625). +-622365448 = 54472535869625 div -87525. +33425 = 54472535869625 rem -87525. +54472535869465 = 54472535869625 band -87525. +-87365 = 54472535869625 bor -87525. +-54472535956830 = 54472535869625 bxor -87525. +-54472535869626 = bnot(54472535869625). +0 = 54472535869625 bsl -377. +16768181217720974853415558020309662149305308050341966976476256634902959995822887523210131218903662344688915902893996573196288000 = 54472535869625 bsr -377. +-2579111915618386289526442805 = -2579111915618386289527399793 + 956988. +-2579111915618386289528356781 = -2579111915618386289527399793 - 956988. +-2468179153903808258442247273103484 = -2579111915618386289527399793 * 956988. +2579111915618386289527399793 = -(-2579111915618386289527399793). +-2579111915618386289527399793 = +(-2579111915618386289527399793). +-2695030570517484325328 = -2579111915618386289527399793 div 956988. +-407729 = -2579111915618386289527399793 rem 956988. +137740 = -2579111915618386289527399793 band 956988. +-2579111915618386289526580545 = -2579111915618386289527399793 bor 956988. +-2579111915618386289526718285 = -2579111915618386289527399793 bxor 956988. +2579111915618386289527399792 = bnot(-2579111915618386289527399793). +-1 = -2579111915618386289527399793 bsl -511. +-17290118597218821021024529513821890190835063660820584345872985981883877694306832228957223603920918937419348656157110128014320605373240673410652865615970155698006925060701575985496064 = -2579111915618386289527399793 bsr -511. +984438258742911654929765 = -63 + 984438258742911654929828. +-984438258742911654929891 = -63 - 984438258742911654929828. +-62019610300803434260579164 = -63 * 984438258742911654929828. +63 = -(-63). +-63 = +(-63). +0 = -63 div 984438258742911654929828. +-63 = -63 rem 984438258742911654929828. +984438258742911654929792 = -63 band 984438258742911654929828. +-27 = -63 bor 984438258742911654929828. +-984438258742911654929819 = -63 bxor 984438258742911654929828. +62 = bnot(-63). +-260019964543335238439042237888598017270995168283403561672355661474066061414638016772564743132206272166910053785743743021637405439442728037865499653462228073009596571030760314864297543856366138955785364634510194292666607675338659293334523473611900765772194770285605421056 = -63 bsl 889. +-1 = -63 bsr 889. +91797984805388653757851517010 = 91798462158182776484622633323 + -477352794122726771116313. +91798939510976899211393749636 = 91798462158182776484622633323 - -477352794122726771116313. +-43820252407377947171728929967148734684504702382698099 = 91798462158182776484622633323 * -477352794122726771116313. +-91798462158182776484622633323 = -(91798462158182776484622633323). +91798462158182776484622633323 = +(91798462158182776484622633323). +-192307 = 91798462158182776484622633323 div -477352794122726771116313. +178378823559311557829232 = 91798462158182776484622633323 rem -477352794122726771116313. +91798008423564741150336221283 = 91798462158182776484622633323 band -477352794122726771116313. +-23618176087392484704273 = 91798462158182776484622633323 bor -477352794122726771116313. +-91798032041740828542820925556 = 91798462158182776484622633323 bxor -477352794122726771116313. +-91798462158182776484622633324 = bnot(91798462158182776484622633323). +5875101578123697695015848532672 = 91798462158182776484622633323 bsl 6. +1434350971221605882572228645 = 91798462158182776484622633323 bsr 6. +-9847688181859085960044534308 = -9854555878181727326733483689 + 6867696322641366688949381. +-9861423574504368693422433070 = -9854555878181727326733483689 - 6867696322641366688949381. +-67678097165852512684070512237042486621497513510146509 = -9854555878181727326733483689 * 6867696322641366688949381. +9854555878181727326733483689 = -(-9854555878181727326733483689). +-9854555878181727326733483689 = +(-9854555878181727326733483689). +-1434 = -9854555878181727326733483689 div 6867696322641366688949381. +-6279351514007494780071335 = -9854555878181727326733483689 rem 6867696322641366688949381. +604647396178036289257477 = -9854555878181727326733483689 band 6867696322641366688949381. +-9848292829255263996333791785 = -9854555878181727326733483689 bor 6867696322641366688949381. +-9848897476651442032623049262 = -9854555878181727326733483689 bxor 6867696322641366688949381. +9854555878181727326733483688 = bnot(-9854555878181727326733483689). +-3049837322744065660367024103424449271192547190672195584 = -9854555878181727326733483689 bsl 88. +-32 = -9854555878181727326733483689 bsr 88. +-986483217873878995 = -37444 + -986483217873841551. +986483217873804107 = -37444 - -986483217873841551. +36937877610068123035644 = -37444 * -986483217873841551. +37444 = -(-37444). +-37444 = +(-37444). +0 = -37444 div -986483217873841551. +-37444 = -37444 rem -986483217873841551. +-986483217873878992 = -37444 band -986483217873841551. +-3 = -37444 bor -986483217873841551. +986483217873878989 = -37444 bxor -986483217873841551. +37443 = bnot(-37444). +-1483309658592056928426329838190592 = -37444 bsl 95. +-1 = -37444 bsr 95. +-349988546208659 = 8353537459 + -349996899746118. +350005253283577 = 8353537459 - -349996899746118. +-2923712212563064302834162 = 8353537459 * -349996899746118. +-8353537459 = -(8353537459). +8353537459 = +(8353537459). +0 = 8353537459 div -349996899746118. +8353537459 = 8353537459 rem -349996899746118. +8338807986 = 8353537459 band -349996899746118. +-349996885016645 = 8353537459 bor -349996899746118. +-350005223824631 = 8353537459 bxor -349996899746118. +-8353537460 = bnot(8353537459). +3983 = 8353537459 bsl -21. +17518637789216768 = 8353537459 bsr -21. +-621886761 = 9885 + -621896646. +621906531 = 9885 - -621896646. +-6147448345710 = 9885 * -621896646. +-9885 = -(9885). +9885 = +(9885). +0 = 9885 div -621896646. +9885 = 9885 rem -621896646. +1048 = 9885 band -621896646. +-621887809 = 9885 bor -621896646. +-621888857 = 9885 bxor -621896646. +-9886 = bnot(9885). +77 = 9885 bsl -7. +1265280 = 9885 bsr -7. +999851860769505 = 999851388881667 + 471887838. +999850916993829 = 999851388881667 - 471887838. +471817710220667078465946 = 999851388881667 * 471887838. +-999851388881667 = -(999851388881667). +999851388881667 = +(999851388881667). +2118832 = 999851388881667 div 471887838. +337316451 = 999851388881667 rem 471887838. +134236930 = 999851388881667 band 471887838. +999851726532575 = 999851388881667 bor 471887838. +999851592295645 = 999851388881667 bxor 471887838. +-999851388881668 = bnot(999851388881667). +127980977776853376 = 999851388881667 bsl 7. +7811338975638 = 999851388881667 bsr 7. +591659823198345342511450469317 = 591659823198345342511446313699 + 4155618. +591659823198345342511442158081 = 591659823198345342511446313699 - 4155618. +2458712211159861475556731507241210982 = 591659823198345342511446313699 * 4155618. +-591659823198345342511446313699 = -(591659823198345342511446313699). +591659823198345342511446313699 = +(591659823198345342511446313699). +142375892875222251542717 = 591659823198345342511446313699 div 4155618. +3779593 = 591659823198345342511446313699 rem 4155618. +1132770 = 591659823198345342511446313699 band 4155618. +591659823198345342511449336547 = 591659823198345342511446313699 bor 4155618. +591659823198345342511448203777 = 591659823198345342511446313699 bxor 4155618. +-591659823198345342511446313700 = bnot(591659823198345342511446313699). +0 = 591659823198345342511446313699 bsl -227. +127608938228185338488286093170817910594843289499086799450886247183853299206472132392911663238479872 = 591659823198345342511446313699 bsr -227. +97342756719869374268 = 97342756789528864195 + -69659489927. +97342756859188354122 = 97342756789528864195 - -69659489927. +-6780846786046596774467353463765 = 97342756789528864195 * -69659489927. +-97342756789528864195 = -(97342756789528864195). +97342756789528864195 = +(97342756789528864195). +-1397408406 = 97342756789528864195 div -69659489927. +7866737833 = 97342756789528864195 rem -69659489927. +97342756789125939521 = 97342756789528864195 band -69659489927. +-69256565253 = 97342756789528864195 bor -69659489927. +-97342756858382504774 = 97342756789528864195 bxor -69659489927. +-97342756789528864196 = bnot(97342756789528864195). +0 = 97342756789528864195 bsl -653. +3638235524365231785090583033971798644167750991518951290046858219409184295614139712285888748466465048994893130074583871738843577903195379854051907486739870268645716009456943061582792921520195791432792560529229417021440 = 97342756789528864195 bsr -653. +389678954744234422040883672 = 389678954839351938193496446 + -95117516152612774. +389678954934469454346109220 = 389678954839351938193496446 - -95117516152612774. +-37065294281265321678205132948334177383201204 = 389678954839351938193496446 * -95117516152612774. +-389678954839351938193496446 = -(389678954839351938193496446). +389678954839351938193496446 = +(389678954839351938193496446). +-4096815924 = 389678954839351938193496446 div -95117516152612774. +14000711464483270 = 389678954839351938193496446 rem -95117516152612774. +389678954821231161930815578 = 389678954839351938193496446 band -95117516152612774. +-76996739889931906 = 389678954839351938193496446 bor -95117516152612774. +-389678954898227901820747484 = 389678954839351938193496446 bxor -95117516152612774. +-389678954839351938193496447 = bnot(389678954839351938193496446). +107114135486366560536017955549582721024 = 389678954839351938193496446 bsl 38. +1417643779275211 = 389678954839351938193496446 bsr 38. +-84775522259114738152919513 = -84775522259114738152919831 + 318. +-84775522259114738152920149 = -84775522259114738152919831 - 318. +-26958616078398486732628506258 = -84775522259114738152919831 * 318. +84775522259114738152919831 = -(-84775522259114738152919831). +-84775522259114738152919831 = +(-84775522259114738152919831). +-266589692638725591675848 = -84775522259114738152919831 div 318. +-167 = -84775522259114738152919831 rem 318. +40 = -84775522259114738152919831 band 318. +-84775522259114738152919553 = -84775522259114738152919831 bor 318. +-84775522259114738152919593 = -84775522259114738152919831 bxor 318. +84775522259114738152919830 = bnot(-84775522259114738152919831). +-331154383824666945909844 = -84775522259114738152919831 bsl -8. +-21702533698333372967147476736 = -84775522259114738152919831 bsr -8. +-54388 = 736 + -55124. +55860 = 736 - -55124. +-40571264 = 736 * -55124. +-736 = -(736). +736 = +(736). +0 = 736 div -55124. +736 = 736 rem -55124. +160 = 736 band -55124. +-54548 = 736 bor -55124. +-54708 = 736 bxor -55124. +-737 = bnot(736). +0 = 736 bsl -388. +463998024968741387203797976219291196168619009649001099961759103128397619581151152160014399417524766586138851213853065216 = 736 bsr -388. +92644319712923691793287 = 8385535252126162 + 92644311327388439667125. +-92644302941853187540963 = 8385535252126162 - 92644311327388439667125. +776872138544766865531637813315783824250 = 8385535252126162 * 92644311327388439667125. +-8385535252126162 = -(8385535252126162). +8385535252126162 = +(8385535252126162). +0 = 8385535252126162 div 92644311327388439667125. +8385535252126162 = 8385535252126162 rem 92644311327388439667125. +6764784243458448 = 8385535252126162 band 92644311327388439667125. +92644312948139448334839 = 8385535252126162 bor 92644311327388439667125. +92644306183355204876391 = 8385535252126162 bxor 92644311327388439667125. +-8385535252126163 = bnot(8385535252126162). +281371872401070158249984 = 8385535252126162 bsl 25. +249908424 = 8385535252126162 bsr 25. +-29189349977685776166969722520 = -29189349977685776166969727281 + 4761. +-29189349977685776166969732042 = -29189349977685776166969727281 - 4761. +-138970495243761980330942871584841 = -29189349977685776166969727281 * 4761. +29189349977685776166969727281 = -(-29189349977685776166969727281). +-29189349977685776166969727281 = +(-29189349977685776166969727281). +-6130928371704636876070096 = -29189349977685776166969727281 div 4761. +-225 = -29189349977685776166969727281 rem 4761. +649 = -29189349977685776166969727281 band 4761. +-29189349977685776166969723169 = -29189349977685776166969727281 bor 4761. +-29189349977685776166969723818 = -29189349977685776166969727281 bxor 4761. +29189349977685776166969727280 = bnot(-29189349977685776166969727281). +-1 = -29189349977685776166969727281 bsl -563. +-881276080166012926281107714324665601604190299552786912735934932557813868523097097100922140056103562533709036837914341738001573003565008318526683760280034928105733555883921301952092024813908339458048 = -29189349977685776166969727281 bsr -563. +-58881726281 = -5 + -58881726276. +58881726271 = -5 - -58881726276. +294408631380 = -5 * -58881726276. +5 = -(-5). +-5 = +(-5). +0 = -5 div -58881726276. +-5 = -5 rem -58881726276. +-58881726280 = -5 band -58881726276. +-1 = -5 bor -58881726276. +58881726279 = -5 bxor -58881726276. +4 = bnot(-5). +-80 = -5 bsl 4. +-1 = -5 bsr 4. +7970339327155153060970032148 = -27584345718728311767683193 + 7997923672873881372737715341. +-8025508018592609684505398534 = -27584345718728311767683193 - 7997923672873881372737715341. +-220617491624554464326103592082184976562231515503963813 = -27584345718728311767683193 * 7997923672873881372737715341. +27584345718728311767683193 = -(-27584345718728311767683193). +-27584345718728311767683193 = +(-27584345718728311767683193). +0 = -27584345718728311767683193 div 7997923672873881372737715341. +-27584345718728311767683193 = -27584345718728311767683193 rem 7997923672873881372737715341. +7970646287930818855716007045 = -27584345718728311767683193 band 7997923672873881372737715341. +-306960775665794745974897 = -27584345718728311767683193 bor 7997923672873881372737715341. +-7970953248706484650461981942 = -27584345718728311767683193 bxor 7997923672873881372737715341. +27584345718728311767683192 = bnot(-27584345718728311767683193). +-53875675231891233921257 = -27584345718728311767683193 bsl -9. +-14123185007988895625053794816 = -27584345718728311767683193 bsr -9. +-58817458847070320482149769860 = -58817458847842812994772557344 + 772492512622787484. +-58817458848615305507395344828 = -58817458847842812994772557344 - 772492512622787484. +-45436046571457497602599660023827514268515482496 = -58817458847842812994772557344 * 772492512622787484. +58817458847842812994772557344 = -(-58817458847842812994772557344). +-58817458847842812994772557344 = +(-58817458847842812994772557344). +-76139843282 = -58817458847842812994772557344 div 772492512622787484. +-225367181021474856 = -58817458847842812994772557344 rem 772492512622787484. +756676585255575936 = -58817458847842812994772557344 band 772492512622787484. +-58817458847826997067405345796 = -58817458847842812994772557344 bor 772492512622787484. +-58817458848583673652660921732 = -58817458847842812994772557344 bxor 772492512622787484. +58817458847842812994772557343 = bnot(-58817458847842812994772557344). +-1 = -58817458847842812994772557344 bsl -213. +-774275172673422732549803392048349440221676987250114196486616281772697653613546737517406978048 = -58817458847842812994772557344 bsr -213. +-59195539 = 91593 + -59287132. +59378725 = 91593 - -59287132. +-5430286281276 = 91593 * -59287132. +-91593 = -(91593). +91593 = +(91593). +0 = 91593 div -59287132. +91593 = 91593 rem -59287132. +82304 = 91593 band -59287132. +-59277843 = 91593 bor -59287132. +-59360147 = 91593 bxor -59287132. +-91594 = bnot(91593). +0 = 91593 bsl -221. +308667799385541068839116989108173629036305871136719831907715371694555136 = 91593 bsr -221. +-5343798581253211314197119350 = -5343798581253211316914762972 + 2717643622. +-5343798581253211319632406594 = -5343798581253211316914762972 - 2717643622. +-14522540131595438502431626308497564584 = -5343798581253211316914762972 * 2717643622. +5343798581253211316914762972 = -(-5343798581253211316914762972). +-5343798581253211316914762972 = +(-5343798581253211316914762972). +-1966335297974257831 = -5343798581253211316914762972 div 2717643622. +-2314059090 = -5343798581253211316914762972 rem 2717643622. +2692465444 = -5343798581253211316914762972 band 2717643622. +-5343798581253211316889584794 = -5343798581253211316914762972 bor 2717643622. +-5343798581253211319582050238 = -5343798581253211316914762972 bxor 2717643622. +5343798581253211316914762971 = bnot(-5343798581253211316914762972). +-607519562123936 = -5343798581253211316914762972 bsl -43. +-47004549412646382184706045100711452082176 = -5343798581253211316914762972 bsr -43. +99984403910220432 = 99984399368494261 + 4541726171. +99984394826768090 = 99984399368494261 - 4541726171. +454101763303606258047004631 = 99984399368494261 * 4541726171. +-99984399368494261 = -(99984399368494261). +99984399368494261 = +(99984399368494261). +22014625 = 99984399368494261 div 4541726171. +861243386 = 99984399368494261 rem 4541726171. +238034065 = 99984399368494261 band 4541726171. +99984403672186367 = 99984399368494261 bor 4541726171. +99984403434152302 = 99984399368494261 bxor 4541726171. +-99984399368494262 = bnot(99984399368494261). +990197530257271489688167149327288051760627712 = 99984399368494261 bsl 93. +0 = 99984399368494261 bsr 93. +79212883456597265552 = 79212883456949412315 + -352146763. +79212883457301559078 = 79212883456949412315 - -352146763. +-27894560497260985401479586345 = 79212883456949412315 * -352146763. +-79212883456949412315 = -(79212883456949412315). +79212883456949412315 = +(79212883456949412315). +-224942812996 = 79212883456949412315 div -352146763. +293680367 = 79212883456949412315 rem -352146763. +79212883456599171217 = 79212883456949412315 band -352146763. +-1905665 = 79212883456949412315 bor -352146763. +-79212883456601076882 = 79212883456949412315 bxor -352146763. +-79212883456949412316 = bnot(79212883456949412315). +37771646240687 = 79212883456949412315 bsl -21. +166121456967508373935226880 = 79212883456949412315 bsr -21. +828850801818857828 = 828856788173989676 + -5986355131848. +828862774529121524 = 828856788173989676 - -5986355131848. +-4961831087452413774035170801248 = 828856788173989676 * -5986355131848. +-828856788173989676 = -(828856788173989676). +828856788173989676 = +(828856788173989676). +-138457 = 828856788173989676 div -5986355131848. +4015683711140 = 828856788173989676 rem -5986355131848. +828856438998172200 = 828856788173989676 band -5986355131848. +-5637179314372 = 828856788173989676 bor -5986355131848. +-828862076177486572 = 828856788173989676 bxor -5986355131848. +-828856788173989677 = bnot(828856788173989676). +207214197043497419 = 828856788173989676 bsl -2. +3315427152695958704 = 828856788173989676 bsr -2. +108892 = 81938 + 26954. +54984 = 81938 - 26954. +2208556852 = 81938 * 26954. +-81938 = -(81938). +81938 = +(81938). +3 = 81938 div 26954. +1076 = 81938 rem 26954. +16386 = 81938 band 26954. +92506 = 81938 bor 26954. +76120 = 81938 bxor 26954. +-81939 = bnot(81938). +1280 = 81938 bsl -6. +5244032 = 81938 bsr -6. +-71218210020096204 = -71453447486777563 + 235237466681359. +-71688684953458922 = -71453447486777563 - 235237466681359. +-16808527972439071951918631548117 = -71453447486777563 * 235237466681359. +71453447486777563 = -(-71453447486777563). +-71453447486777563 = +(-71453447486777563). +-303 = -71453447486777563 div 235237466681359. +-176495082325786 = -71453447486777563 rem 235237466681359. +5988602253317 = -71453447486777563 band 235237466681359. +-71224198622349521 = -71453447486777563 bor 235237466681359. +-71230187224602838 = -71453447486777563 bxor 235237466681359. +71453447486777562 = bnot(-71453447486777563). +-8931680935847196 = -71453447486777563 bsl -3. +-571627579894220504 = -71453447486777563 bsr -3. +5537188928 = -55 + 5537188983. +-5537189038 = -55 - 5537188983. +-304545394065 = -55 * 5537188983. +55 = -(-55). +-55 = +(-55). +0 = -55 div 5537188983. +-55 = -55 rem 5537188983. +5537188929 = -55 band 5537188983. +-1 = -55 bor 5537188983. +-5537188930 = -55 bxor 5537188983. +54 = bnot(-55). +-944892805120 = -55 bsl 34. +-1 = -55 bsr 34. +-64978773561394548434684261 = -552972 + -64978773561394548434131289. +64978773561394548433578317 = -552972 - -64978773561394548434131289. +35931442373791466236718447140908 = -552972 * -64978773561394548434131289. +552972 = -(-552972). +-552972 = +(-552972). +0 = -552972 div -64978773561394548434131289. +-552972 = -552972 rem -64978773561394548434131289. +-64978773561394548434663772 = -552972 band -64978773561394548434131289. +-20489 = -552972 bor -64978773561394548434131289. +64978773561394548434643283 = -552972 bxor -64978773561394548434131289. +552971 = bnot(-552972). +-1 = -552972 bsl -888. +-1141140951059183916429476701347093831796640795206430430992744879655851254861708042942529136026209259783179256047700706874292693338567652448845722812494564936414782818063663435167780487470972195163956703592653739352416185551169596085347445351191428494052238781860093657874432 = -552972 bsr -888. +-7931161752156336473679481555 = -7931161752156336685154151379 + 211474669824. +-7931161752156336896628821203 = -7931161752156336685154151379 - 211474669824. +-1677239812857998620522352805416939287296 = -7931161752156336685154151379 * 211474669824. +7931161752156336685154151379 = -(-7931161752156336685154151379). +-7931161752156336685154151379 = +(-7931161752156336685154151379). +-37504074406438623 = -7931161752156336685154151379 div 211474669824. +-106507939027 = -7931161752156336685154151379 rem 211474669824. +73627222016 = -7931161752156336685154151379 band 211474669824. +-7931161752156336547306703571 = -7931161752156336685154151379 bor 211474669824. +-7931161752156336620933925587 = -7931161752156336685154151379 bxor 211474669824. +7931161752156336685154151378 = bnot(-7931161752156336685154151379). +-12313272113186103921130374203648000551845741068461661724876816962650434751748552394322870652014840162966396119852328739173423034400378461241792451490464791783699965196730140308013088409468006269539623602257087703480757573735187413571225145620726804090846183424 = -7931161752156336685154151379 bsl 768. +-1 = -7931161752156336685154151379 bsr 768. +714957416338999897061 = 714958245882488652896 + -829543488755835. +714959075425977408731 = 714958245882488652896 - -829543488755835. +-593088957604111741020359952209648160 = 714958245882488652896 * -829543488755835. +-714958245882488652896 = -(714958245882488652896). +714958245882488652896 = +(714958245882488652896). +-861869 = 714958245882488652896 div -829543488755835. +428771985897281 = 714958245882488652896 rem -829543488755835. +714957981904603087872 = 714958245882488652896 band -829543488755835. +-565565603190811 = 714958245882488652896 bor -829543488755835. +-714958547470206278683 = 714958245882488652896 bxor -829543488755835. +-714958245882488652897 = bnot(714958245882488652896). +45757327736479273785344 = 714958245882488652896 bsl 6. +11171222591913885201 = 714958245882488652896 bsr 6. +996378621616514 = 996378621622899 + -6385. +996378621629284 = 996378621622899 - -6385. +-6361877499062210115 = 996378621622899 * -6385. +-996378621622899 = -(996378621622899). +996378621622899 = +(996378621622899). +-156049901585 = 996378621622899 div -6385. +2674 = 996378621622899 rem -6385. +996378621616643 = 996378621622899 band -6385. +-129 = 996378621622899 bor -6385. +-996378621616772 = 996378621622899 bxor -6385. +-996378621622900 = bnot(996378621622899). +1191685205215865960980475238890439746942267230329209039566398371784516186461927373794119083796406545393401897213207408688658831871831161338124049068588648198137657255470407110838856633687430191838787047644626681856 = 996378621622899 bsl 658. +0 = 996378621622899 bsr 658. +-7856694390025 = -7856982256154 + 287866129. +-7857270122283 = -7856982256154 - 287866129. +-2261759067700738407866 = -7856982256154 * 287866129. +7856982256154 = -(-7856982256154). +-7856982256154 = +(-7856982256154). +-27293 = -7856982256154 div 287866129. +-251997357 = -7856982256154 rem 287866129. +17306880 = -7856982256154 band 287866129. +-7856711696905 = -7856982256154 bor 287866129. +-7856729003785 = -7856982256154 bxor 287866129. +7856982256153 = bnot(-7856982256154). +-30691336939 = -7856982256154 bsl -8. +-2011387457575424 = -7856982256154 bsr -8. +5458631248550523 = 5458631248551254 + -731. +5458631248551985 = 5458631248551254 - -731. +-3990259442690966674 = 5458631248551254 * -731. +-5458631248551254 = -(5458631248551254). +5458631248551254 = +(5458631248551254). +-7467347809235 = 5458631248551254 div -731. +469 = 5458631248551254 rem -731. +5458631248551172 = 5458631248551254 band -731. +-649 = 5458631248551254 bor -731. +-5458631248551821 = 5458631248551254 bxor -731. +-5458631248551255 = bnot(5458631248551254). +2342024938910654820051888536507780965891187943829321942042078042290919638154856722380825766850939794692762065322883142094692838537470620714612390306960835945300214088204288 = 5458631248551254 bsl 517. +0 = 5458631248551254 bsr 517. +37877562043706634320734816 = -219639748162211523 + 37877562263346382482946339. +-37877562482986130645157862 = -219639748162211523 - 37877562263346382482946339. +-8319418236519886147530691974581819176464297 = -219639748162211523 * 37877562263346382482946339. +219639748162211523 = -(-219639748162211523). +-219639748162211523 = +(-219639748162211523). +0 = -219639748162211523 div 37877562263346382482946339. +-219639748162211523 = -219639748162211523 rem 37877562263346382482946339. +37877562046028814865936673 = -219639748162211523 band 37877562263346382482946339. +-2322180545201857 = -219639748162211523 bor 37877562263346382482946339. +-37877562048350995411138530 = -219639748162211523 bxor 37877562263346382482946339. +219639748162211522 = bnot(-219639748162211523). +-1 = -219639748162211523 bsl -89. +-135950419234279581409087868002800581870616576 = -219639748162211523 bsr -89. +69778474864706102665228970530 = 69778474864697313953383437367 + 8788711845533163. +69778474864688525241537904204 = 69778474864697313953383437367 - 8788711845533163. +613262908606603356476071407813496285731901821 = 69778474864697313953383437367 * 8788711845533163. +-69778474864697313953383437367 = -(69778474864697313953383437367). +69778474864697313953383437367 = +(69778474864697313953383437367). +7939556568823 = 69778474864697313953383437367 div 8788711845533163. +1978346045060218 = 69778474864697313953383437367 rem 8788711845533163. +4239721133118499 = 69778474864697313953383437367 band 8788711845533163. +69778474864701862944095852031 = 69778474864697313953383437367 bor 8788711845533163. +69778474864697623222962733532 = 69778474864697313953383437367 bxor 8788711845533163. +-69778474864697313953383437368 = bnot(69778474864697313953383437367). +1116455597835157023254134997872 = 69778474864697313953383437367 bsl 4. +4361154679043582122086464835 = 69778474864697313953383437367 bsr 4. +68916954866495927 = 68916954866738219 + -242292. +68916954866980511 = 68916954866738219 - -242292. +-16698026828571736557948 = 68916954866738219 * -242292. +-68916954866738219 = -(68916954866738219). +68916954866738219 = +(68916954866738219). +-284437599535 = 68916954866738219 div -242292. +203999 = 68916954866738219 rem -242292. +68916954866664456 = 68916954866738219 band -242292. +-168529 = 68916954866738219 bor -242292. +-68916954866832985 = 68916954866738219 bxor -242292. +-68916954866738220 = bnot(68916954866738219). +2603608942112997136130701629317963579392 = 68916954866738219 bsl 75. +0 = 68916954866738219 bsr 75. +798375855535459387752176231 = -558 + 798375855535459387752176789. +-798375855535459387752177347 = -558 - 798375855535459387752176789. +-445493727388786338365714648262 = -558 * 798375855535459387752176789. +558 = -(-558). +-558 = +(-558). +0 = -558 div 798375855535459387752176789. +-558 = -558 rem 798375855535459387752176789. +798375855535459387752176784 = -558 band 798375855535459387752176789. +-553 = -558 bor 798375855535459387752176789. +-798375855535459387752177337 = -558 bxor 798375855535459387752176789. +557 = bnot(-558). +-1 = -558 bsl -555. +-65808469782825627329712108005982938785363813781011679969810097360533071331713095608251834770285424759004354789598944545439749569484313571530290009759357637261136331014144 = -558 bsr -555. +31341992556638337 = 31341992588568319 + -31929982. +31341992620498301 = 31341992588568319 - -31929982. +-1000749259197119831440258 = 31341992588568319 * -31929982. +-31341992588568319 = -(31341992588568319). +31341992588568319 = +(31341992588568319). +-981585037 = 31341992588568319 div -31929982. +25688985 = 31341992588568319 rem -31929982. +31341992575778946 = 31341992588568319 band -31929982. +-19140609 = 31341992588568319 bor -31929982. +-31341992594919555 = 31341992588568319 bxor -31929982. +-31341992588568320 = bnot(31341992588568319). +0 = 31341992588568319 bsl -82. +151560576313962352491548366831053308952576 = 31341992588568319 bsr -82. +-71152585374235 = -71152585374226 + -9. +-71152585374217 = -71152585374226 - -9. +640373268368034 = -71152585374226 * -9. +71152585374226 = -(-71152585374226). +-71152585374226 = +(-71152585374226). +7905842819358 = -71152585374226 div -9. +-4 = -71152585374226 rem -9. +-71152585374234 = -71152585374226 band -9. +-1 = -71152585374226 bor -9. +71152585374233 = -71152585374226 bxor -9. +71152585374225 = bnot(-71152585374226). +-1401777304902370023267168911069106526994726800019700595916679983405075563365032665475935344090222914425442753620093033909959262208 = -71152585374226 bsl 383. +-1 = -71152585374226 bsr 383. +-79667436337 = -421 + -79667435916. +79667435495 = -421 - -79667435916. +33539990520636 = -421 * -79667435916. +421 = -(-421). +-421 = +(-421). +0 = -421 div -79667435916. +-421 = -421 rem -79667435916. +-79667435952 = -421 band -79667435916. +-385 = -421 bor -79667435916. +79667435567 = -421 bxor -79667435916. +420 = bnot(-421). +-1 = -421 bsl -43. +-3703155162349568 = -421 bsr -43. +83279812644292437334481164553 = 551264226118 + 83279812644292436783216938435. +-83279812644292436231952712317 = 551264226118 - 83279812644292436783216938435. +45909181468607901372980522896879525045330 = 551264226118 * 83279812644292436783216938435. +-551264226118 = -(551264226118). +551264226118 = +(551264226118). +0 = 551264226118 div 83279812644292436783216938435. +551264226118 = 551264226118 rem 83279812644292436783216938435. +550844238146 = 551264226118 band 83279812644292436783216938435. +83279812644292436783636926407 = 551264226118 bor 83279812644292436783216938435. +83279812644292436232792688261 = 551264226118 bxor 83279812644292436783216938435. +-551264226119 = bnot(551264226118). +36994715978618109952 = 551264226118 bsl 26. +8214 = 551264226118 bsr 26. +87569964599575541 = 87569964599575535 + 6. +87569964599575529 = 87569964599575535 - 6. +525419787597453210 = 87569964599575535 * 6. +-87569964599575535 = -(87569964599575535). +87569964599575535 = +(87569964599575535). +14594994099929255 = 87569964599575535 div 6. +5 = 87569964599575535 rem 6. +6 = 87569964599575535 band 6. +87569964599575535 = 87569964599575535 bor 6. +87569964599575529 = 87569964599575535 bxor 6. +-87569964599575536 = bnot(87569964599575535). +350279858398302140 = 87569964599575535 bsl 2. +21892491149893883 = 87569964599575535 bsr 2. +-79139683474112 = 3266 + -79139683477378. +79139683480644 = 3266 - -79139683477378. +-258470206237116548 = 3266 * -79139683477378. +-3266 = -(3266). +3266 = +(3266). +0 = 3266 div -79139683477378. +3266 = 3266 rem -79139683477378. +2114 = 3266 band -79139683477378. +-79139683476226 = 3266 bor -79139683477378. +-79139683478340 = 3266 bxor -79139683477378. +-3267 = bnot(3266). +0 = 3266 bsl -97. +517518357543174653161029083594752 = 3266 bsr -97. +-528826609416005235279143258934 = -528822366958813963365687686735 + -4242457191271913455572199. +-528818124501622691452232114536 = -528822366958813963365687686735 - -4242457191271913455572199. +2243506253609855016895612866281530019759954648087080265 = -528822366958813963365687686735 * -4242457191271913455572199. +528822366958813963365687686735 = -(-528822366958813963365687686735). +-528822366958813963365687686735 = +(-528822366958813963365687686735). +124650 = -528822366958813963365687686735 div -4242457191271913455572199. +-78066769951128613081385 = -528822366958813963365687686735 rem -4242457191271913455572199. +-528822378175597133599814448879 = -528822366958813963365687686735 band -4242457191271913455572199. +-4231240408101679328810055 = -528822366958813963365687686735 bor -4242457191271913455572199. +528818146935189031920485638824 = -528822366958813963365687686735 bxor -4242457191271913455572199. +528822366958813963365687686734 = bnot(-528822366958813963365687686735). +-1 = -528822366958813963365687686735 bsl -694. +-43463711218466338955572487038712869586135496388142499896172260074134030839763399010045581644463349710359458383073992347886041147194909733968081404679983369726128835813905894046541858902553215110731412580659716174189772604269171919017738240 = -528822366958813963365687686735 bsr -694. +797319233226109 = 797319233226116 + -7. +797319233226123 = 797319233226116 - -7. +-5581234632582812 = 797319233226116 * -7. +-797319233226116 = -(797319233226116). +797319233226116 = +(797319233226116). +-113902747603730 = 797319233226116 div -7. +6 = 797319233226116 rem -7. +797319233226112 = 797319233226116 band -7. +-3 = 797319233226116 bor -7. +-797319233226115 = 797319233226116 bxor -7. +-797319233226117 = bnot(797319233226116). +0 = 797319233226116 bsl -678. +999929314538887397457460885892402574280556113199216091903682678906350648933619397885255043195645170578694143264320226870569053104450492035830990612081822756284334114092839013846886137293561013683556295378342835969327104 = 797319233226116 bsr -678. +74658793917586461856003213 = 74658793917586461855943656 + 59557. +74658793917586461855884099 = 74658793917586461855943656 - 59557. +4446453789349696908754436320392 = 74658793917586461855943656 * 59557. +-74658793917586461855943656 = -(74658793917586461855943656). +74658793917586461855943656 = +(74658793917586461855943656). +1253568747881633760195 = 74658793917586461855943656 div 59557. +10041 = 74658793917586461855943656 rem 59557. +34976 = 74658793917586461855943656 band 59557. +74658793917586461855968237 = 74658793917586461855943656 bor 59557. +74658793917586461855933261 = 74658793917586461855943656 bxor 59557. +-74658793917586461855943657 = bnot(74658793917586461855943656). +180513887256515809585267167850601915130806022438912 = 74658793917586461855943656 bsl 81. +30 = 74658793917586461855943656 bsr 81. +328255484272303502 = 328255484352167823 + -79864321. +328255484432032144 = 328255484352167823 - -79864321. +-26215901372312008061943183 = 328255484352167823 * -79864321. +-328255484352167823 = -(328255484352167823). +328255484352167823 = +(328255484352167823). +-4110164341 = 328255484352167823 div -79864321. +59790362 = 328255484352167823 rem -79864321. +328255484280724879 = 328255484352167823 band -79864321. +-8421377 = 328255484352167823 bor -79864321. +-328255484289146256 = 328255484352167823 bxor -79864321. +-328255484352167824 = bnot(328255484352167823). +41031935544020977 = 328255484352167823 bsl -3. +2626043874817342584 = 328255484352167823 bsr -3. +-77397692958105440346617 = -77397692957873165781294 + -232274565323. +-77397692957640891215971 = -77397692957873165781294 - -232274565323. +17977515488793007732415981534467962 = -77397692957873165781294 * -232274565323. +77397692957873165781294 = -(-77397692957873165781294). +-77397692957873165781294 = +(-77397692957873165781294). +333216393496 = -77397692957873165781294 div -232274565323. +-92041442086 = -77397692957873165781294 rem -232274565323. +-77397692957959335696880 = -77397692957873165781294 band -232274565323. +-146104649737 = -77397692957873165781294 bor -232274565323. +77397692957813231047143 = -77397692957873165781294 bxor -232274565323. +77397692957873165781293 = bnot(-77397692957873165781294). +-2476726174651941305001408 = -77397692957873165781294 bsl 5. +-2418677904933536430666 = -77397692957873165781294 bsr 5. +558623004797590356 = -71322676152166 + 558694327473742522. +-558765650149894688 = -71322676152166 - 558694327473742522. +-39847574586461917438398376602652 = -71322676152166 * 558694327473742522. +71322676152166 = -(-71322676152166). +-71322676152166 = +(-71322676152166). +0 = -71322676152166 div 558694327473742522. +-71322676152166 = -71322676152166 rem 558694327473742522. +558623382767739034 = -71322676152166 band 558694327473742522. +-377970148678 = -71322676152166 bor 558694327473742522. +-558623760737887712 = -71322676152166 bxor 558694327473742522. +71322676152165 = bnot(-71322676152166). +-9521519476763252171233415047488689967244976902650839894022363196561548524908584988430404213853455719885438976 = -71322676152166 bsl 316. +-1 = -71322676152166 bsr 316. +41146241257 = 48132563528 + -6986322271. +55118885799 = 48132563528 - -6986322271. +-336269600535988732088 = 48132563528 * -6986322271. +-48132563528 = -(48132563528). +48132563528 = +(48132563528). +-6 = 48132563528 div -6986322271. +6214629902 = 48132563528 rem -6986322271. +43293876736 = 48132563528 band -6986322271. +-2147635479 = 48132563528 bor -6986322271. +-45441512215 = 48132563528 bxor -6986322271. +-48132563529 = bnot(48132563528). +376035652 = 48132563528 bsl -7. +6160968131584 = 48132563528 bsr -7. +-24099764783368 = -24152264348513 + 52499565145. +-24204763913658 = -24152264348513 - 52499565145. +-1267983375564019227379385 = -24152264348513 * 52499565145. +24152264348513 = -(-24152264348513). +-24152264348513 = +(-24152264348513). +-460 = -24152264348513 div 52499565145. +-2464381813 = -24152264348513 rem 52499565145. +34763753497 = -24152264348513 band 52499565145. +-24134528536865 = -24152264348513 bor 52499565145. +-24169292290362 = -24152264348513 bxor 52499565145. +24152264348512 = bnot(-24152264348513). +-1545744918304832 = -24152264348513 bsl 6. +-377379130446 = -24152264348513 bsr 6. +5539295 = 7879 + 5531416. +-5523537 = 7879 - 5531416. +43582026664 = 7879 * 5531416. +-7879 = -(7879). +7879 = +(7879). +0 = 7879 div 5531416. +7879 = 7879 rem 5531416. +1536 = 7879 band 5531416. +5537759 = 7879 bor 5531416. +5536223 = 7879 bxor 5531416. +-7880 = bnot(7879). +984 = 7879 bsl -3. +63032 = 7879 bsr -3. +58172169302819364 = 58172169262996546 + 39822818. +58172169223173728 = 58172169262996546 - 39822818. +2316579709225505585986628 = 58172169262996546 * 39822818. +-58172169262996546 = -(58172169262996546). +58172169262996546 = +(58172169262996546). +1460774806 = 58172169262996546 div 39822818. +24673238 = 58172169262996546 rem 39822818. +1836098 = 58172169262996546 band 39822818. +58172169300983266 = 58172169262996546 bor 39822818. +58172169299147168 = 58172169262996546 bxor 39822818. +-58172169262996547 = bnot(58172169262996546). +0 = 58172169262996546 bsl -583. +1841631485232425883936462493764158299079473394554733660956254705586690260117048334965703753053493372091793188222396847239863698388545793745284307475542137916335156259717659697262445460631584768 = 58172169262996546 bsr -583. +-524374052553398976132976328851 = 515975493941411182952824 + -524374568528892917544159281675. +524375084504386858955342234499 = 515975493941411182952824 - -524374568528892917544159281675. +-270564427007009890743217691173433382599028713252700200 = 515975493941411182952824 * -524374568528892917544159281675. +-515975493941411182952824 = -(515975493941411182952824). +515975493941411182952824 = +(515975493941411182952824). +0 = 515975493941411182952824 div -524374568528892917544159281675. +515975493941411182952824 = 515975493941411182952824 rem -524374568528892917544159281675. +24793884116422100140400 = 515975493941411182952824 band -524374568528892917544159281675. +-524374077347283092555076469251 = 515975493941411182952824 bor -524374568528892917544159281675. +-524374102141167208977176609651 = 515975493941411182952824 bxor -524374568528892917544159281675. +-515975493941411182952825 = bnot(515975493941411182952824). +0 = 515975493941411182952824 bsl -383. +10165234804733592749048078667408891909669893160380371407515909658118733874352020029652328005348506648156359666196339278592623350726306824192 = 515975493941411182952824 bsr -383. +65522935517544286668033 = 65522935517544323655995 + -36987962. +65522935517544360643957 = 65522935517544323655995 - -36987962. +-2423559849051379776703644132190 = 65522935517544323655995 * -36987962. +-65522935517544323655995 = -(65522935517544323655995). +65522935517544323655995 = +(65522935517544323655995). +-1771466498141863 = 65522935517544323655995 div -36987962. +24402789 = 65522935517544323655995 rem -36987962. +65522935517544288782594 = 65522935517544323655995 band -36987962. +-2114561 = 65522935517544323655995 bor -36987962. +-65522935517544290897155 = 65522935517544323655995 bxor -36987962. +-65522935517544323655996 = bnot(65522935517544323655995). +255948966865407514281 = 65522935517544323655995 bsl -8. +16773871492491346855934720 = 65522935517544323655995 bsr -8. +-5488878154392571 = -5488877264739374 + -889653197. +-5488876375086177 = -5488877264739374 - -889653197. +4883197206515999450878678 = -5488877264739374 * -889653197. +5488877264739374 = -(-5488877264739374). +-5488877264739374 = +(-5488877264739374). +6169681 = -5488877264739374 div -889653197. +-838619217 = -5488877264739374 rem -889653197. +-5488877868916718 = -5488877264739374 band -889653197. +-285475853 = -5488877264739374 bor -889653197. +5488877583440865 = -5488877264739374 bxor -889653197. +5488877264739373 = bnot(-5488877264739374). +-171527414523106 = -5488877264739374 bsl -5. +-175644072471659968 = -5488877264739374 bsr -5. +-975351984431271311365207286 = -275691 + -975351984431271311364931595. +975351984431271311364655904 = -275691 - -975351984431271311364931595. +268895763939841619101509356357145 = -275691 * -975351984431271311364931595. +275691 = -(-275691). +-275691 = +(-275691). +0 = -275691 div -975351984431271311364931595. +-275691 = -275691 rem -975351984431271311364931595. +-975351984431271311365207275 = -275691 band -975351984431271311364931595. +-11 = -275691 bor -975351984431271311364931595. +975351984431271311365207264 = -275691 bxor -975351984431271311364931595. +275690 = bnot(-275691). +-8822112 = -275691 bsl 5. +-8616 = -275691 bsr 5. +-547541251554946824913030723705 = -547541251554946824865281451454 + -47749272251. +-547541251554946824817532179203 = -547541251554946824865281451454 - -47749272251. +26144696289150433026320340423217485802954 = -547541251554946824865281451454 * -47749272251. +547541251554946824865281451454 = -(-547541251554946824865281451454). +-547541251554946824865281451454 = +(-547541251554946824865281451454). +11467007259853679081 = -547541251554946824865281451454 div -47749272251. +-2628970123 = -547541251554946824865281451454 rem -47749272251. +-547541251554946824874241800128 = -547541251554946824865281451454 band -47749272251. +-38788923577 = -547541251554946824865281451454 bor -47749272251. +547541251554946824835452876551 = -547541251554946824865281451454 bxor -47749272251. +547541251554946824865281451453 = bnot(-547541251554946824865281451454). +-68442656444368353108160181432 = -547541251554946824865281451454 bsl -3. +-4380330012439574598922251611632 = -547541251554946824865281451454 bsr -3. +-893417919092660 = -272535657287 + -893145383435373. +892872847778086 = -272535657287 - -893145383435373. +243413964127409022641013051 = -272535657287 * -893145383435373. +272535657287 = -(-272535657287). +-272535657287 = +(-272535657287). +0 = -272535657287 div -893145383435373. +-272535657287 = -272535657287 rem -893145383435373. +-893353154576239 = -272535657287 band -893145383435373. +-64764516421 = -272535657287 bor -893145383435373. +893288390059818 = -272535657287 bxor -893145383435373. +272535657286 = bnot(-272535657287). +-1 = -272535657287 bsl -257. +-63114946297853855695226119544089564744479648846237524090765976921107249191234398809227264 = -272535657287 bsr -257. +4868490155316553 = -6893813846725 + 4875383969163278. +-4882277783010003 = -6893813846725 - 4875383969163278. +-33609989514718896288790564550 = -6893813846725 * 4875383969163278. +6893813846725 = -(-6893813846725). +-6893813846725 = +(-6893813846725). +0 = -6893813846725 div 4875383969163278. +-6893813846725 = -6893813846725 rem 4875383969163278. +4873184929130506 = -6893813846725 band 4875383969163278. +-4694773813953 = -6893813846725 bor 4875383969163278. +-4877879702944459 = -6893813846725 bxor 4875383969163278. +6893813846724 = bnot(-6893813846725). +-53857920678 = -6893813846725 bsl -7. +-882408172380800 = -6893813846725 bsr -7. +88531884 = -345648 + 88877532. +-89223180 = -345648 - 88877532. +-30720341180736 = -345648 * 88877532. +345648 = -(-345648). +-345648 = +(-345648). +0 = -345648 div 88877532. +-345648 = -345648 rem 88877532. +88615376 = -345648 band 88877532. +-83492 = -345648 bor 88877532. +-88698868 = -345648 bxor 88877532. +345647 = bnot(-345648). +-1 = -345648 bsl -22. +-1449752788992 = -345648 bsr -22. +-7182728122643761525984115570 = 6713161799745 + -7182728122643768239145915315. +7182728122643774952307715060 = 6713161799745 - -7182728122643768239145915315. +-48218816050886264279813462417710758594675 = 6713161799745 * -7182728122643768239145915315. +-6713161799745 = -(6713161799745). +6713161799745 = +(6713161799745). +0 = 6713161799745 div -7182728122643768239145915315. +6713161799745 = 6713161799745 rem -7182728122643768239145915315. +34378565697 = 6713161799745 band -7182728122643768239145915315. +-7182728122643761560362681267 = 6713161799745 bor -7182728122643768239145915315. +-7182728122643761594741246964 = 6713161799745 bxor -7182728122643768239145915315. +-6713161799746 = bnot(6713161799745). +400135 = 6713161799745 bsl -24. +112628165557270609920 = 6713161799745 bsr -24. +677832337812136399 = 9225519627 + 677832328586616772. +-677832319361097145 = 9225519627 - 677832328586616772. +6253355451190946199613384044 = 9225519627 * 677832328586616772. +-9225519627 = -(9225519627). +9225519627 = +(9225519627). +0 = 9225519627 div 677832328586616772. +9225519627 = 9225519627 rem 677832328586616772. +10633728 = 9225519627 band 677832328586616772. +677832337801502671 = 9225519627 bor 677832328586616772. +677832337790868943 = 9225519627 bxor 677832328586616772. +-9225519628 = bnot(9225519627). +0 = 9225519627 bsl -73. +87132569347201742402958114422784 = 9225519627 bsr -73. +9582164918175358592318162218 = 9582164555961441837585497692 + 362213916754732664526. +9582164193747525082852833166 = 9582164555961441837585497692 - 362213916754732664526. +3470793354803167580245453739625958279418983273992 = 9582164555961441837585497692 * 362213916754732664526. +-9582164555961441837585497692 = -(9582164555961441837585497692). +9582164555961441837585497692 = +(9582164555961441837585497692). +26454435 = 9582164555961441837585497692 div 362213916754732664526. +39077955621505624882 = 9582164555961441837585497692 rem 362213916754732664526. +20910215406356022860 = 9582164555961441837585497692 band 362213916754732664526. +9582164897265143185962139358 = 9582164555961441837585497692 bor 362213916754732664526. +9582164876354927779606116498 = 9582164555961441837585497692 bxor 362213916754732664526. +-9582164555961441837585497693 = bnot(9582164555961441837585497692). +5336676852399686120194739528601269773861139218240560986439407944118521240903591147655063511501698925729523074806326316313266339822586508845390959601173850920852656732314354269052161587782993297354961379357339760459776 = 9582164555961441837585497692 bsl 627. +0 = 9582164555961441837585497692 bsr 627. +-341814826686116351943 = -4927348123992595974 + -336887478562123755969. +331960130438131159995 = -4927348123992595974 - -336887478562123755969. +1659961885489676382779337545251587868806 = -4927348123992595974 * -336887478562123755969. +4927348123992595974 = -(-4927348123992595974). +-4927348123992595974 = +(-4927348123992595974). +0 = -4927348123992595974 div -336887478562123755969. +-4927348123992595974 = -4927348123992595974 rem -336887478562123755969. +-337185055900363997126 = -4927348123992595974 band -336887478562123755969. +-4629770785752354817 = -4927348123992595974 bor -336887478562123755969. +332555285114611642309 = -4927348123992595974 bxor -336887478562123755969. +4927348123992595973 = bnot(-4927348123992595974). +-1 = -4927348123992595974 bsl -78. +-1489199592331088637185911635105985232633856 = -4927348123992595974 bsr -78. +-9392058631397766 = -9392647166833978 + 588535436212. +-9393235702270190 = -9392647166833978 - 588535436212. +-5527905697518041181213211336 = -9392647166833978 * 588535436212. +9392647166833978 = -(-9392647166833978). +-9392647166833978 = +(-9392647166833978). +-15959 = -9392647166833978 div 588535436212. +-210140326670 = -9392647166833978 rem 588535436212. +38689440388 = -9392647166833978 band 588535436212. +-9392097320838154 = -9392647166833978 bor 588535436212. +-9392136010278542 = -9392647166833978 bxor 588535436212. +9392647166833977 = bnot(-9392647166833978). +-385989066975312680106234949556957333505791913465331437801724024961539883462898484456837898372667490205649698957301760942139537259995987721900399294371093260505471227570348896124947635073654541278753777384183516606078780440576 = -9392647166833978 bsl 693. +-1 = -9392647166833978 bsr 693. +-4961296591226261882489848 = -27175 + -4961296591226261882462673. +4961296591226261882435498 = -27175 - -4961296591226261882462673. +134823234866573666655923138775 = -27175 * -4961296591226261882462673. +27175 = -(-27175). +-27175 = +(-27175). +0 = -27175 div -4961296591226261882462673. +-27175 = -27175 rem -4961296591226261882462673. +-4961296591226261882465271 = -27175 band -4961296591226261882462673. +-24577 = -27175 bor -4961296591226261882462673. +4961296591226261882440694 = -27175 bxor -4961296591226261882462673. +27174 = bnot(-27175). +-1 = -27175 bsl -622. +-472962660918743725076957086124059359565633715379637207464178301520968638110717040932839129057119628101290148783349716257736074641431341276559891019300274545920364209273300933908470558831411200 = -27175 bsr -622. +-4518784533548335134124 = 311734 + -4518784533548335445858. +4518784533548335757592 = 311734 - -4518784533548335445858. +-1408658777781156801879097772 = 311734 * -4518784533548335445858. +-311734 = -(311734). +311734 = +(311734). +0 = 311734 div -4518784533548335445858. +311734 = 311734 rem -4518784533548335445858. +311446 = 311734 band -4518784533548335445858. +-4518784533548335445570 = 311734 bor -4518784533548335445858. +-4518784533548335757016 = 311734 bxor -4518784533548335445858. +-311735 = bnot(311734). +0 = 311734 bsl -44. +5484082524369977344 = 311734 bsr -44. +21275919429780858025821 = 21275919429779874153175 + 983872646. +21275919429778890280529 = 21275919429779874153175 - 983872646. +20932795145460335980631296551050 = 21275919429779874153175 * 983872646. +-21275919429779874153175 = -(21275919429779874153175). +21275919429779874153175 = +(21275919429779874153175). +21624668107481 = 21275919429779874153175 div 983872646. +730288449 = 21275919429779874153175 rem 983872646. +8683654 = 21275919429779874153175 band 983872646. +21275919429780849342167 = 21275919429779874153175 bor 983872646. +21275919429780840658513 = 21275919429779874153175 bxor 983872646. +-21275919429779874153176 = bnot(21275919429779874153175). +0 = 21275919429779874153175 bsl -618. +23143319841309774529218182426277225740061130868854095682779067358923745953370169676763359692335210842040982434765721084951676031564401410968549003375379240299973134221202155012423338818501642607167135757107200 = 21275919429779874153175 bsr -618. +-3339502453047626442278 = 515477399815852872455 + -3854979852863479314733. +4370457252679332187188 = 515477399815852872455 - -3854979852863479314733. +-1987154990896565405463692075357393051379515 = 515477399815852872455 * -3854979852863479314733. +-515477399815852872455 = -(515477399815852872455). +515477399815852872455 = +(515477399815852872455). +0 = 515477399815852872455 div -3854979852863479314733. +515477399815852872455 = 515477399815852872455 rem -3854979852863479314733. +202997527792201105923 = 515477399815852872455 band -3854979852863479314733. +-3542499980839827548201 = 515477399815852872455 bor -3854979852863479314733. +-3745497508632028654124 = 515477399815852872455 bxor -3854979852863479314733. +-515477399815852872456 = bnot(515477399815852872455). +507242775050453558664206926574664259334949441075912623324632243027555334273558726787570601860054774624788985787370365824153046190847018043828663361852299868268568559992782257302728452053620442820422112636486933611624357943645384009909453643531871800768007627880329628193139185418240 = 515477399815852872455 bsl 867. +0 = 515477399815852872455 bsr 867. +-984265841769192217048 = -984174278811462362262 + -91562957729854786. +-984082715853732507476 = -984174278811462362262 - -91562957729854786. +90113907889624247031558125489786485932 = -984174278811462362262 * -91562957729854786. +984174278811462362262 = -(-984174278811462362262). +-984174278811462362262 = +(-984174278811462362262). +10748 = -984174278811462362262 div -91562957729854786. +-55609130983122334 = -984174278811462362262 rem -91562957729854786. +-984265476721666913750 = -984174278811462362262 band -91562957729854786. +-365047525303298 = -984174278811462362262 bor -91562957729854786. +984265111674141610452 = -984174278811462362262 bxor -91562957729854786. +984174278811462362261 = bnot(-984174278811462362262). +-144460950166215404152568275607761337046688597771011357538634752049580194971460310077327877110179810448579921881907952828108767232 = -984174278811462362262 bsl 356. +-1 = -984174278811462362262 bsr 356. +6618887092721257518 = 6594487817164322823 + 24399275556934695. +6570088541607388128 = 6594487817164322823 - 24399275556934695. +160900725407841093880781221309043985 = 6594487817164322823 * 24399275556934695. +-6594487817164322823 = -(6594487817164322823). +6594487817164322823 = +(6594487817164322823). +270 = 6594487817164322823 div 24399275556934695. +6683416791955173 = 6594487817164322823 rem 24399275556934695. +1129211462422535 = 6594487817164322823 band 24399275556934695. +6617757881258834983 = 6594487817164322823 bor 24399275556934695. +6616628669796412448 = 6594487817164322823 bxor 24399275556934695. +-6594487817164322824 = bnot(6594487817164322823). +2881758163258708472009229807991022233836603862499931168191263405427528350157214552701788026582250369607836895526645645608425613267889411032227731280317762877832901610956911686886424172368524206909418827646354584671451685390926741598329380603293086612065494790832128 = 6594487817164322823 bsl 816. +0 = 6594487817164322823 bsr 816. +9294547468162 = 55151716 + 9294492316446. +-9294437164730 = 55151716 - 9294492316446. +512607200600811921336 = 55151716 * 9294492316446. +-55151716 = -(55151716). +55151716 = +(55151716). +0 = 55151716 div 9294492316446. +55151716 = 55151716 rem 9294492316446. +38371332 = 55151716 band 9294492316446. +9294509096830 = 55151716 bor 9294492316446. +9294470725498 = 55151716 bxor 9294492316446. +-55151717 = bnot(55151716). +1764854912 = 55151716 bsl 5. +1723491 = 55151716 bsr 5. +6847874423084035 = 6763526927266637 + 84347495817398. +6679179431449239 = 6763526927266637 - 84347495817398. +570486559208481411318209550526 = 6763526927266637 * 84347495817398. +-6763526927266637 = -(6763526927266637). +6763526927266637 = +(6763526927266637). +80 = 6763526927266637 div 84347495817398. +15727261874797 = 6763526927266637 rem 84347495817398. +4552707579908 = 6763526927266637 band 84347495817398. +6843321715504127 = 6763526927266637 bor 84347495817398. +6838769007924219 = 6763526927266637 bxor 84347495817398. +-6763526927266638 = bnot(6763526927266637). +72861841021346594950469669310145622757531257645856262087320576422892113884140671863370529611731381331417851598231496342896189603706299843552141018223872279795445980361061454826487169875371327280810397754559309096395131065861144576 = 6763526927266637 bsl 711. +0 = 6763526927266637 bsr 711. +-80167305584397671 = -2243787451848889 + -77923518132548782. +75679730680699893 = -2243787451848889 - -77923518132548782. +174843812189732329080955885003198 = -2243787451848889 * -77923518132548782. +2243787451848889 = -(-2243787451848889). +-2243787451848889 = +(-2243787451848889). +0 = -2243787451848889 div -77923518132548782. +-2243787451848889 = -2243787451848889 rem -77923518132548782. +-78812679878540478 = -2243787451848889 band -77923518132548782. +-1354625705857193 = -2243787451848889 bor -77923518132548782. +77458054172683285 = -2243787451848889 bxor -77923518132548782. +2243787451848888 = bnot(-2243787451848889). +-1 = -2243787451848889 bsl -64. +-41390572880057349064804798377754624 = -2243787451848889 bsr -64. +65170746308571457407813069 = 7625473793728984683221438 + 57545272514842472724591631. +-49919798721113488041370193 = 7625473793728984683221438 - 57545272514842472724591631. +438809967514924101539814551646840646904176094585378 = 7625473793728984683221438 * 57545272514842472724591631. +-7625473793728984683221438 = -(7625473793728984683221438). +7625473793728984683221438 = +(7625473793728984683221438). +0 = 7625473793728984683221438 div 57545272514842472724591631. +7625473793728984683221438 = 7625473793728984683221438 rem 57545272514842472724591631. +7293718166728473898913806 = 7625473793728984683221438 band 57545272514842472724591631. +57877028141842983508899263 = 7625473793728984683221438 bor 57545272514842472724591631. +50583309975114509609985457 = 7625473793728984683221438 bxor 57545272514842472724591631. +-7625473793728984683221439 = bnot(7625473793728984683221438). +488030322798655019726172032 = 7625473793728984683221438 bsl 6. +119148028027015385675334 = 7625473793728984683221438 bsr 6. +455461316337253539450 = 5 + 455461316337253539445. +-455461316337253539440 = 5 - 455461316337253539445. +2277306581686267697225 = 5 * 455461316337253539445. +-5 = -(5). +5 = +(5). +0 = 5 div 455461316337253539445. +5 = 5 rem 455461316337253539445. +5 = 5 band 455461316337253539445. +455461316337253539445 = 5 bor 455461316337253539445. +455461316337253539440 = 5 bxor 455461316337253539445. +-6 = bnot(5). +640 = 5 bsl 7. +0 = 5 bsr 7. +-83155929185183823425319556194 = -973 + -83155929185183823425319555221. +83155929185183823425319554248 = -973 - -83155929185183823425319555221. +80910719097183860192835927230033 = -973 * -83155929185183823425319555221. +973 = -(-973). +-973 = +(-973). +0 = -973 div -83155929185183823425319555221. +-973 = -973 rem -83155929185183823425319555221. +-83155929185183823425319556061 = -973 band -83155929185183823425319555221. +-133 = -973 bor -83155929185183823425319555221. +83155929185183823425319555928 = -973 bxor -83155929185183823425319555221. +972 = bnot(-973). +-1 = -973 bsl -926. +-551936131267121475258832859306279466631971807943188022102838904996646980063275701698092945100692798280286467837470154868351864411893918324920836698689510334353191615202094443262570906360157660665413947103968791351892059132305975847540610225280473447712219195406678019400605653532672 = -973 bsr -926. +-47638341697598172697398233 = -47638341697598172697392918 + -5315. +-47638341697598172697387603 = -47638341697598172697392918 - -5315. +253197786122734287886643359170 = -47638341697598172697392918 * -5315. +47638341697598172697392918 = -(-47638341697598172697392918). +-47638341697598172697392918 = +(-47638341697598172697392918). +8962999378663814242218 = -47638341697598172697392918 div -5315. +-4248 = -47638341697598172697392918 rem -5315. +-47638341697598172697393112 = -47638341697598172697392918 band -5315. +-5121 = -47638341697598172697392918 bor -5315. +47638341697598172697387991 = -47638341697598172697392918 bxor -5315. +47638341697598172697392917 = bnot(-47638341697598172697392918). +-1 = -47638341697598172697392918 bsl -653. +-1780507485120814963816905410710360908621808249817282740913166131099101078121931803923807431316809972356332314045330221899193989705837846871622622680409917642160646232237830315179310472531087430300491432785096334823082950656 = -47638341697598172697392918 bsr -653. +-72339946578891567854753983517 = -519829187751 + -72339946578891567334924795766. +72339946578891566815095608015 = -519829187751 - -72339946578891567334924795766. +37604415672055934689617280357709343862266 = -519829187751 * -72339946578891567334924795766. +519829187751 = -(-519829187751). +-519829187751 = +(-519829187751). +0 = -519829187751 div -72339946578891567334924795766. +-519829187751 = -519829187751 rem -72339946578891567334924795766. +-72339946578891567442436030456 = -519829187751 band -72339946578891567334924795766. +-412317953061 = -519829187751 bor -72339946578891567334924795766. +72339946578891567030118077395 = -519829187751 bxor -72339946578891567334924795766. +519829187750 = bnot(-519829187751). +-16634534008032 = -519829187751 bsl 5. +-16244662118 = -519829187751 bsr 5. +662264339361468698253212818 = 662264339361468697367817694 + 885395124. +662264339361468696482422570 = 662264339361468697367817694 - 885395124. +586365616869725658128097420788524056 = 662264339361468697367817694 * 885395124. +-662264339361468697367817694 = -(662264339361468697367817694). +662264339361468697367817694 = +(662264339361468697367817694). +747987335156669213 = 662264339361468697367817694 div 885395124. +96700282 = 662264339361468697367817694 rem 885395124. +71568532 = 662264339361468697367817694 band 885395124. +662264339361468698181644286 = 662264339361468697367817694 bor 885395124. +662264339361468698110075754 = 662264339361468697367817694 bxor 885395124. +-662264339361468697367817695 = bnot(662264339361468697367817694). +0 = 662264339361468697367817694 bsl -99. +419759893650658802452305031968642128034251818337904361472 = 662264339361468697367817694 bsr -99. +5551635323614192491 = 5551635323614192528 + -37. +5551635323614192565 = 5551635323614192528 - -37. +-205410506973725123536 = 5551635323614192528 * -37. +-5551635323614192528 = -(5551635323614192528). +5551635323614192528 = +(5551635323614192528). +-150044197935518716 = 5551635323614192528 div -37. +36 = 5551635323614192528 rem -37. +5551635323614192528 = 5551635323614192528 band -37. +-37 = 5551635323614192528 bor -37. +-5551635323614192565 = 5551635323614192528 bxor -37. +-5551635323614192529 = bnot(5551635323614192528). +173488603862943516 = 5551635323614192528 bsl -5. +177652330355654160896 = 5551635323614192528 bsr -5. +-7922868694817488596 = -7922868694817488664 + 68. +-7922868694817488732 = -7922868694817488664 - 68. +-538755071247589229152 = -7922868694817488664 * 68. +7922868694817488664 = -(-7922868694817488664). +-7922868694817488664 = +(-7922868694817488664). +-116512774923786598 = -7922868694817488664 div 68. +0 = -7922868694817488664 rem 68. +64 = -7922868694817488664 band 68. +-7922868694817488660 = -7922868694817488664 bor 68. +-7922868694817488724 = -7922868694817488664 bxor 68. +7922868694817488663 = bnot(-7922868694817488664). +-1 = -7922868694817488664 bsl -779. +-25191213038852209044292937828015099025257271256952343863342072868140826251837776329735427118358786135914611789331358205206094825046490733380868271669321943129071304927884001954104300135133945628429755034568960848769397911798990400314322641925013799698432 = -7922868694817488664 bsr -779. +-3439612141528135279856463 = -563955965296 + -3439612141527571323891167. +3439612141527007367925871 = -563955965296 - -3439612141527571323891167. +1939789785519023253963531752332940432 = -563955965296 * -3439612141527571323891167. +563955965296 = -(-563955965296). +-563955965296 = +(-563955965296). +0 = -563955965296 div -3439612141527571323891167. +-563955965296 = -563955965296 rem -3439612141527571323891167. +-3439612141528129776598528 = -563955965296 band -3439612141527571323891167. +-5503257935 = -563955965296 bor -3439612141527571323891167. +3439612141528124273340593 = -563955965296 bxor -3439612141527571323891167. +563955965295 = bnot(-563955965296). +-541940339221058495495078070836423910083159626032191856894560088569230104128272088057519676587986666583808881852814217227628213601444998530249842725234595206451724231979262967335650884326365777356470287467946345934412644176179721180848261386551415577421540255883551834112 = -563955965296 bsl 857. +-1 = -563955965296 bsr 857. +74846914192869903940589 = 74846914187975425696327 + 4894478244262. +74846914183080947452065 = 74846914187975425696327 - 4894478244262. +366336593143190538994560613742225674 = 74846914187975425696327 * 4894478244262. +-74846914187975425696327 = -(74846914187975425696327). +74846914187975425696327 = +(74846914187975425696327). +15292112959 = 74846914187975425696327 div 4894478244262. +1352928105069 = 74846914187975425696327 rem 4894478244262. +27394054 = 74846914187975425696327 band 4894478244262. +74846914192869876546535 = 74846914187975425696327 bor 4894478244262. +74846914192869849152481 = 74846914187975425696327 bxor 4894478244262. +-74846914187975425696328 = bnot(74846914187975425696327). +9355864273496928212040 = 74846914187975425696327 bsl -3. +598775313503803405570616 = 74846914187975425696327 bsr -3. +27729278293582772620091 = 4568124133468954 + 27729273725458639151137. +-27729269157334505682183 = 4568124133468954 - 27729273725458639151137. +126670764508834179830296294753703300698 = 4568124133468954 * 27729273725458639151137. +-4568124133468954 = -(4568124133468954). +4568124133468954 = +(4568124133468954). +0 = 4568124133468954 div 27729273725458639151137. +4568124133468954 = 4568124133468954 rem 27729273725458639151137. +4521193025757184 = 4568124133468954 band 27729273725458639151137. +27729273772389746862907 = 4568124133468954 bor 27729273725458639151137. +27729269251196721105723 = 4568124133468954 bxor 27729273725458639151137. +-4568124133468955 = bnot(4568124133468954). +2338879556336104448 = 4568124133468954 bsl 9. +8922117448181 = 4568124133468954 bsr 9. +613853613779 = -9 + 613853613788. +-613853613797 = -9 - 613853613788. +-5524682524092 = -9 * 613853613788. +9 = -(-9). +-9 = +(-9). +0 = -9 div 613853613788. +-9 = -9 rem 613853613788. +613853613780 = -9 band 613853613788. +-1 = -9 bor 613853613788. +-613853613781 = -9 bxor 613853613788. +8 = bnot(-9). +-2 = -9 bsl -3. +-72 = -9 bsr -3. +-751857743733561031471334097 = -751857796426246214427919613 + 52692685182956585516. +-751857849118931397384505129 = -751857796426246214427919613 - 52692685182956585516. +-39617406169439652737022658089983852693808125308 = -751857796426246214427919613 * 52692685182956585516. +751857796426246214427919613 = -(-751857796426246214427919613). +-751857796426246214427919613 = +(-751857796426246214427919613). +-14268731 = -751857796426246214427919613 div 52692685182956585516. +-45882952911021619417 = -751857796426246214427919613 rem 52692685182956585516. +37686689255231390208 = -751857796426246214427919613 band 52692685182956585516. +-751857781420250286702724305 = -751857796426246214427919613 bor 52692685182956585516. +-751857819106939541934114513 = -751857796426246214427919613 bxor 52692685182956585516. +751857796426246214427919612 = bnot(-751857796426246214427919613). +-1 = -751857796426246214427919613 bsl -515. +-80646119400903926685731137644641022840104071743500325701578097649871103598441439752640723378625217462686403820548821827652110516083907867978512175536328261507327541587791080046198784 = -751857796426246214427919613 bsr -515. +96996894948146060580 = -345647483986177414 + 97342542432132237994. +-97688189916118415408 = -345647483986177414 - 97342542432132237994. +-33646204876484223153688510072955467516 = -345647483986177414 * 97342542432132237994. +345647483986177414 = -(-345647483986177414). +-345647483986177414 = +(-345647483986177414). +0 = -345647483986177414 div 97342542432132237994. +-345647483986177414 = -345647483986177414 rem 97342542432132237994. +96999656947326190122 = -345647483986177414 band 97342542432132237994. +-2761999180129542 = -345647483986177414 bor 97342542432132237994. +-97002418946506319664 = -345647483986177414 bxor 97342542432132237994. +345647483986177413 = bnot(-345647483986177414). +-675092742160503 = -345647483986177414 bsl -9. +-176971511800922835968 = -345647483986177414 bsr -9. +-569275717333336783105837 = -36525449459652 + -569275717296811333646185. +569275717260285884186533 = -36525449459652 - -569275717296811333646185. +20793051440731822236629637395201227620 = -36525449459652 * -569275717296811333646185. +36525449459652 = -(-36525449459652). +-36525449459652 = +(-36525449459652). +0 = -36525449459652 div -569275717296811333646185. +-36525449459652 = -36525449459652 rem -569275717296811333646185. +-569275717332064800602092 = -36525449459652 band -569275717296811333646185. +-1271982503745 = -36525449459652 bor -569275717296811333646185. +569275717330792818098347 = -36525449459652 bxor -569275717296811333646185. +36525449459651 = bnot(-36525449459652). +-1 = -36525449459652 bsl -71. +-86243279150004899242472755634896896 = -36525449459652 bsr -71. +-613417895681019799187662 = 952595656291 + -613417895681972394843953. +613417895682924990500244 = 952595656291 - -613417895681972394843953. +-584339222917812668483720392567758323 = 952595656291 * -613417895681972394843953. +-952595656291 = -(952595656291). +952595656291 = +(952595656291). +0 = 952595656291 div -613417895681972394843953. +952595656291 = 952595656291 rem -613417895681972394843953. +601431744579 = 952595656291 band -613417895681972394843953. +-613417895681621230932241 = 952595656291 bor -613417895681972394843953. +-613417895682222662676820 = 952595656291 bxor -613417895681972394843953. +-952595656292 = bnot(952595656291). +0 = 952595656291 bsl -58. +274567004333241643758732181504 = 952595656291 bsr -58. +-813328478207627017348061145252 = -813328514393849498522623473498 + 36186222481174562328246. +-813328550580071979697185801744 = -813328514393849498522623473498 - 36186222481174562328246. +-29431286572139025330671384515676263999375822557824508 = -813328514393849498522623473498 * 36186222481174562328246. +813328514393849498522623473498 = -(-813328514393849498522623473498). +-813328514393849498522623473498 = +(-813328514393849498522623473498). +-22476192 = -813328514393849498522623473498 div 36186222481174562328246. +-30152253650116999354266 = -813328514393849498522623473498 rem 36186222481174562328246. +16549625396562181163174 = -813328514393849498522623473498 band 36186222481174562328246. +-813328494757252413910242308426 = -813328514393849498522623473498 bor 36186222481174562328246. +-813328511306877810472423471600 = -813328514393849498522623473498 bxor 36186222481174562328246. +813328514393849498522623473497 = bnot(-813328514393849498522623473498). +-13972877480903395438802672539183330885632 = -813328514393849498522623473498 bsl 34. +-47341950377091386968 = -813328514393849498522623473498 bsr 34. +-246978517966895 = 419452542 + -246978937419437. +246979356871979 = 419452542 - -246978937419437. +-103595943121041769858854 = 419452542 * -246978937419437. +-419452542 = -(419452542). +419452542 = +(419452542). +0 = 419452542 div -246978937419437. +419452542 = 419452542 rem -246978937419437. +402653266 = 419452542 band -246978937419437. +-246978920620161 = 419452542 bor -246978937419437. +-246979323273427 = 419452542 bxor -246978937419437. +-419452543 = bnot(419452542). +870262426717854295966065008483023523861908222876206258988889127949838197693295466809932634868090555026014842069068940974580873883527751424812991148802465193116752608480453708173520085712896 = 419452542 bsl 599. +0 = 419452542 bsr 599. +7346833259 = 7356131752 + -9298493. +7365430245 = 7356131752 - -9298493. +-68400939603049736 = 7356131752 * -9298493. +-7356131752 = -(7356131752). +7356131752 = +(7356131752). +-791 = 7356131752 div -9298493. +1023789 = 7356131752 rem -9298493. +7355763072 = 7356131752 band -9298493. +-8929813 = 7356131752 bor -9298493. +-7364692885 = 7356131752 bxor -9298493. +-7356131753 = bnot(7356131752). +0 = 7356131752 bsl -99. +4662502415390368373544927386193285349376 = 7356131752 bsr -99. +87759834593295 = 87759834951214 + -357919. +87759835309133 = 87759834951214 - -357919. +-31410912365903563666 = 87759834951214 * -357919. +-87759834951214 = -(87759834951214). +87759834951214 = +(87759834951214). +-245194680 = 87759834951214 div -357919. +280294 = 87759834951214 rem -357919. +87759834875936 = 87759834951214 band -357919. +-282641 = 87759834951214 bor -357919. +-87759835158577 = 87759834951214 bxor -357919. +-87759834951215 = bnot(87759834951214). +26523782599410241230670220080936124416 = 87759834951214 bsl 78. +0 = 87759834951214 bsr 78. +-2886281968227901 = 657 + -2886281968228558. +2886281968229215 = 657 - -2886281968228558. +-1896287253126162606 = 657 * -2886281968228558. +-657 = -(657). +657 = +(657). +0 = 657 div -2886281968228558. +657 = 657 rem -2886281968228558. +528 = 657 band -2886281968228558. +-2886281968228429 = 657 bor -2886281968228558. +-2886281968228957 = 657 bxor -2886281968228558. +-658 = bnot(657). +0 = 657 bsl -647. +383683006179556129106847967352971699258220944545574895921987773985257444461580933495601243780545665235784703665900995277199677312248788833901055806343359324375239744135000841242169388071170391146496 = 657 bsr -647. +-386217743711406946466 = 58569695 + -386217743711465516161. +386217743711524085856 = 58569695 - -386217743711465516161. +-22620655452768703284567340895 = 58569695 * -386217743711465516161. +-58569695 = -(58569695). +58569695 = +(58569695). +0 = 58569695 div -386217743711465516161. +58569695 = 58569695 rem -386217743711465516161. +20812639 = 58569695 band -386217743711465516161. +-386217743711427759105 = 58569695 bor -386217743711465516161. +-386217743711448571744 = 58569695 bxor -386217743711465516161. +-58569696 = bnot(58569695). +0 = 58569695 bsl -75. +2212700516639182759395076341760 = 58569695 bsr -75. +935526528909122527908635 = -77259628266821 + 935526528986382156175456. +-935526529063641784442277 = -77259628266821 - 935526528986382156175456. +-72278431863237226442629106583259345376 = -77259628266821 * 935526528986382156175456. +77259628266821 = -(-77259628266821). +-77259628266821 = +(-77259628266821). +0 = -77259628266821 div 935526528986382156175456. +-77259628266821 = -77259628266821 rem 935526528986382156175456. +935526528916011801384992 = -77259628266821 band 935526528986382156175456. +-6889273476357 = -77259628266821 bor 935526528986382156175456. +-935526528922901074861349 = -77259628266821 bxor 935526528986382156175456. +77259628266820 = bnot(-77259628266821). +-3060569192057672483181072812828412690300928 = -77259628266821 bsl 95. +-1 = -77259628266821 bsr 95. +-6590 = 91 + -6681. +6772 = 91 - -6681. +-607971 = 91 * -6681. +-91 = -(91). +91 = +(91). +0 = 91 div -6681. +91 = 91 rem -6681. +67 = 91 band -6681. +-6657 = 91 bor -6681. +-6724 = 91 bxor -6681. +-92 = bnot(91). +0 = 91 bsl -834. +10424561026324885878408437351857641210622713058670117520716687691641227297948457114001683472760164728656286861355715898107080457315574709118961989479129506981866686248104433205225115659178348274553194562996355270081238721512852480435990598506756643487744 = 91 bsr -834. +-996686702714 = -996686696237 + -6477. +-996686689760 = -996686696237 - -6477. +6455539731527049 = -996686696237 * -6477. +996686696237 = -(-996686696237). +-996686696237 = +(-996686696237). +153880916 = -996686696237 div -6477. +-3305 = -996686696237 rem -6477. +-996686700397 = -996686696237 band -6477. +-2317 = -996686696237 bor -6477. +996686698080 = -996686696237 bxor -6477. +996686696236 = bnot(-996686696237). +-470182267614744941834464066213763821417723793602057510484725260491419503503826402776606703887379095487930410700653614976462478299254219106840621721874843375463342071648306975473664 = -996686696237 bsl 557. +-1 = -996686696237 bsr 557. +23987 = -72861 + 96848. +-169709 = -72861 - 96848. +-7056442128 = -72861 * 96848. +72861 = -(-72861). +-72861 = +(-72861). +0 = -72861 div 96848. +-72861 = -72861 rem 96848. +25152 = -72861 band 96848. +-1165 = -72861 bor 96848. +-26317 = -72861 bxor 96848. +72860 = bnot(-72861). +-11483478293901992599543452562946255381807659531941531638693522422906990135972233049433019414388679354019246888006979682304 = -72861 bsl 386. +-1 = -72861 bsr 386. +69291931734315477708 = 69291931734273229525 + 42248183. +69291931734230981342 = 69291931734273229525 - 42248183. +2927458212333082772973203075 = 69291931734273229525 * 42248183. +-69291931734273229525 = -(69291931734273229525). +69291931734273229525 = +(69291931734273229525). +1640116256225 = 69291931734273229525 div 42248183. +4540350 = 69291931734273229525 rem 42248183. +8389333 = 69291931734273229525 band 42248183. +69291931734307088375 = 69291931734273229525 bor 42248183. +69291931734298699042 = 69291931734273229525 bxor 42248183. +-69291931734273229526 = bnot(69291931734273229525). +277167726937092918100 = 69291931734273229525 bsl 2. +17322982933568307381 = 69291931734273229525 bsr 2. +-2832927225825495987764600788 = 53892974 + -2832927225825495987818493762. +2832927225825495987872386736 = 53892974 - -2832927225825495987818493762. +-152674873325305583808606401034628188 = 53892974 * -2832927225825495987818493762. +-53892974 = -(53892974). +53892974 = +(53892974). +0 = 53892974 div -2832927225825495987818493762. +53892974 = 53892974 rem -2832927225825495987818493762. +33816622 = 53892974 band -2832927225825495987818493762. +-2832927225825495987798417410 = 53892974 bor -2832927225825495987818493762. +-2832927225825495987832234032 = 53892974 bxor -2832927225825495987818493762. +-53892975 = bnot(53892974). +0 = 53892974 bsl -954. +8206311791222122719336074185028366232549318925851085049614006002078274316481391281454698884993554155752540906133304458402903004243858966440184097786445439478278285019852093783289495160356162789520040176852907588015026362705746248987255627889422108774672178028038905455213511938638920115516604416 = 53892974 bsr -954. +-68611845705004 = -286215 + -68611845418789. +68611845132574 = -286215 - -68611845418789. +19637739336538693635 = -286215 * -68611845418789. +286215 = -(-286215). +-286215 = +(-286215). +0 = -286215 div -68611845418789. +-286215 = -286215 rem -68611845418789. +-68611845422887 = -286215 band -68611845418789. +-282117 = -286215 bor -68611845418789. +68611845140770 = -286215 bxor -68611845418789. +286214 = bnot(-286215). +-436275029945650252199650317932251510839763192091237655245680473241785045032372664532584673480623708264409113813922556919931954276878660438935470080 = -286215 bsl 469. +-1 = -286215 bsr 469. +-512732740390153 = 49352993 + -512732789743146. +512732839096139 = 49352993 - -512732789743146. +-25304897783063956335978 = 49352993 * -512732789743146. +-49352993 = -(49352993). +49352993 = +(49352993). +0 = 49352993 div -512732789743146. +49352993 = 49352993 rem -512732789743146. +3211520 = 49352993 band -512732789743146. +-512732743601673 = 49352993 bor -512732789743146. +-512732746813193 = 49352993 bxor -512732789743146. +-49352994 = bnot(49352993). +0 = 49352993 bsl -74. +932251679890000880576088768512 = 49352993 bsr -74. +531482923494787 = 531448591528994 + 34331965793. +531414259563201 = 531448591528994 - 34331965793. +18245674865111451575702242 = 531448591528994 * 34331965793. +-531448591528994 = -(531448591528994). +531448591528994 = +(531448591528994). +15479 = 531448591528994 div 34331965793. +24093019147 = 531448591528994 rem 34331965793. +6509572128 = 531448591528994 band 34331965793. +531476413922659 = 531448591528994 bor 34331965793. +531469904350531 = 531448591528994 bxor 34331965793. +-531448591528995 = bnot(531448591528994). +1037985530330 = 531448591528994 bsl -9. +272101678862844928 = 531448591528994 bsr -9. +-8489992563173627951104 = -8489992562348759397818 + -824868553286. +-8489992561523890844532 = -8489992562348759397818 - -824868553286. +7003127882313521318655030205129948 = -8489992562348759397818 * -824868553286. +8489992562348759397818 = -(-8489992562348759397818). +-8489992562348759397818 = +(-8489992562348759397818). +10292539979 = -8489992562348759397818 div -824868553286. +-232712576824 = -8489992562348759397818 rem -824868553286. +-8489992562623733790718 = -8489992562348759397818 band -824868553286. +-549894160386 = -8489992562348759397818 bor -824868553286. +8489992562073839630332 = -8489992562348759397818 bxor -824868553286. +8489992562348759397817 = bnot(-8489992562348759397818). +-120650051 = -8489992562348759397818 bsl -46. +-597430114690189927379778990245937152 = -8489992562348759397818 bsr -46. +57476985649093700 = -5453973 + 57476985654547673. +-57476985660001646 = -5453973 - 57476985654547673. +-313477927881290335754829 = -5453973 * 57476985654547673. +5453973 = -(-5453973). +-5453973 = +(-5453973). +0 = -5453973 div 57476985654547673. +-5453973 = -5453973 rem 57476985654547673. +57476985653298249 = -5453973 band 57476985654547673. +-4204549 = -5453973 bor 57476985654547673. +-57476985657502798 = -5453973 bxor 57476985654547673. +5453972 = bnot(-5453973). +-1 = -5453973 bsl -258. +-2526107713255652489211518863283154459432889832307270655903890391297559981606842662912 = -5453973 bsr -258. +-25599391846587506442715334 = -25599391855744375581629931 + 9156869138914597. +-25599391864901244720544528 = -25599391855744375581629931 - 9156869138914597. +-234410281258847347773596153584801468002807 = -25599391855744375581629931 * 9156869138914597. +25599391855744375581629931 = -(-25599391855744375581629931). +-25599391855744375581629931 = +(-25599391855744375581629931). +-2795648978 = -25599391855744375581629931 div 9156869138914597. +-5858042449298065 = -25599391855744375581629931 rem 9156869138914597. +8867702833157 = -25599391855744375581629931 band 9156869138914597. +-25599391846596374145548491 = -25599391855744375581629931 bor 9156869138914597. +-25599391846605241848381648 = -25599391855744375581629931 bxor 9156869138914597. +25599391855744375581629930 = bnot(-25599391855744375581629931). +-3276722157535280074448631168 = -25599391855744375581629931 bsl 7. +-199995248873002934231484 = -25599391855744375581629931 bsr 7. +-6847695562908190 = -6847695562916685 + 8495. +-6847695562925180 = -6847695562916685 - 8495. +-58171173806977239075 = -6847695562916685 * 8495. +6847695562916685 = -(-6847695562916685). +-6847695562916685 = +(-6847695562916685). +-806085410584 = -6847695562916685 div 8495. +-5605 = -6847695562916685 rem 8495. +8227 = -6847695562916685 band 8495. +-6847695562916417 = -6847695562916685 bor 8495. +-6847695562924644 = -6847695562916685 bxor 8495. +6847695562916684 = bnot(-6847695562916685). +-6738305309360558911484947669955640850019842627085458412460504846319924825267906933730937584276189428450798629439606252598836059693897767836404630423790207590427281228188700926861329466744518920219435577244877120735671164418722952535662164634929364198997228429265378305827143680 = -6847695562916685 bsl 867. +-1 = -6847695562916685 bsr 867. +-78957516664711610812330364 = 4787424172 + -78957516664711615599754536. +78957516664711620387178708 = 4787424172 - -78957516664711615599754536. +-378003123841733207931437142913044192 = 4787424172 * -78957516664711615599754536. +-4787424172 = -(4787424172). +4787424172 = +(4787424172). +0 = 4787424172 div -78957516664711615599754536. +4787424172 = 4787424172 rem -78957516664711615599754536. +4299702920 = 4787424172 band -78957516664711615599754536. +-78957516664711615112033284 = 4787424172 bor -78957516664711615599754536. +-78957516664711619411736204 = 4787424172 bxor -78957516664711615599754536. +-4787424173 = bnot(4787424172). +598428021 = 4787424172 bsl -3. +38299393376 = 4787424172 bsr -3. +-68926612091105 = -72337987637636 + 3411375546531. +-75749363184167 = -72337987637636 - 3411375546531. +-246772042112293231084840716 = -72337987637636 * 3411375546531. +72337987637636 = -(-72337987637636). +-72337987637636 = +(-72337987637636). +-21 = -72337987637636 div 3411375546531. +-699101160485 = -72337987637636 rem 3411375546531. +2268914081824 = -72337987637636 band 3411375546531. +-71195526172929 = -72337987637636 bor 3411375546531. +-73464440254753 = -72337987637636 bxor 3411375546531. +72337987637635 = bnot(-72337987637636). +-5337601379034546763031602584879104 = -72337987637636 bsl 66. +-1 = -72337987637636 bsr 66. +366997256288629962285709 = 366997256282391586138967 + 6238376146742. +366997256276153209992225 = 366997256282391586138967 - 6238376146742. +2289466929511832274961970530796295514 = 366997256282391586138967 * 6238376146742. +-366997256282391586138967 = -(366997256282391586138967). +366997256282391586138967 = +(366997256282391586138967). +58828972099 = 366997256282391586138967 div 6238376146742. +2639338387509 = 366997256282391586138967 rem 6238376146742. +35972555542 = 366997256282391586138967 band 6238376146742. +366997256288593989730167 = 366997256282391586138967 bor 6238376146742. +366997256288558017174625 = 366997256282391586138967 bxor 6238376146742. +-366997256282391586138968 = bnot(366997256282391586138967). +62107066059550596845185833471899010129125068295383964890558683963063224157463976245047477053513779620293728948896445559395991275930251116411787149312 = 366997256282391586138967 bsl 416. +0 = 366997256282391586138967 bsr 416. +-907849704 = -832371363 + -75478341. +-756893022 = -832371363 - -75478341. +62826009575148783 = -832371363 * -75478341. +832371363 = -(-832371363). +-832371363 = +(-832371363). +11 = -832371363 div -75478341. +-2109612 = -832371363 rem -75478341. +-905969639 = -832371363 band -75478341. +-1880065 = -832371363 bor -75478341. +904089574 = -832371363 bxor -75478341. +832371362 = bnot(-832371363). +-67168464082180747975884535694311826060656310067695512550203247399763807063777091066513318216137651486880217824718100934881705984 = -832371363 bsl 395. +-1 = -832371363 bsr 395. +33349 = 33351 + -2. +33353 = 33351 - -2. +-66702 = 33351 * -2. +-33351 = -(33351). +33351 = +(33351). +-16675 = 33351 div -2. +1 = 33351 rem -2. +33350 = 33351 band -2. +-1 = 33351 bor -2. +-33351 = 33351 bxor -2. +-33352 = bnot(33351). +1067232 = 33351 bsl 5. +1042 = 33351 bsr 5. +-489348 = 377 + -489725. +490102 = 377 - -489725. +-184626325 = 377 * -489725. +-377 = -(377). +377 = +(377). +0 = 377 div -489725. +377 = 377 rem -489725. +257 = 377 band -489725. +-489605 = 377 bor -489725. +-489862 = 377 bxor -489725. +-378 = bnot(377). +23 = 377 bsl -4. +6032 = 377 bsr -4. +49559794142498886273111105 = -8485389 + 49559794142498886281596494. +-49559794142498886290081883 = -8485389 - 49559794142498886281596494. +-420534132059024482166109792626166 = -8485389 * 49559794142498886281596494. +8485389 = -(-8485389). +-8485389 = +(-8485389). +0 = -8485389 div 49559794142498886281596494. +-8485389 = -8485389 rem 49559794142498886281596494. +49559794142498886281593922 = -8485389 band 49559794142498886281596494. +-8482817 = -8485389 bor 49559794142498886281596494. +-49559794142498886290076739 = -8485389 bxor 49559794142498886281596494. +8485388 = bnot(-8485389). +-16574 = -8485389 bsl -9. +-4344519168 = -8485389 bsr -9. +-2286769281656285670353 = -44554 + -2286769281656285625799. +2286769281656285581245 = -44554 - -2286769281656285625799. +101884718574914149771848646 = -44554 * -2286769281656285625799. +44554 = -(-44554). +-44554 = +(-44554). +0 = -44554 div -2286769281656285625799. +-44554 = -44554 rem -2286769281656285625799. +-2286769281656285626320 = -44554 band -2286769281656285625799. +-44033 = -44554 bor -2286769281656285625799. +2286769281656285582287 = -44554 bxor -2286769281656285625799. +44553 = bnot(-44554). +-1 = -44554 bsl -591. +-361088899718601094284300429607218738129313534045565495395325227865307315155645917099008882536697778224055407500156045627407096798855266088022640276092018629127585730603029014293512192 = -44554 bsr -591. +49523073771743412 = 54281959185659176 + -4758885413915764. +59040844599574940 = 54281959185659176 - -4758885413915764. +-258321623807404275527695677650464 = 54281959185659176 * -4758885413915764. +-54281959185659176 = -(54281959185659176). +54281959185659176 = +(54281959185659176). +-11 = 54281959185659176 div -4758885413915764. +1934219632585772 = 54281959185659176 rem -4758885413915764. +54061892131369224 = 54281959185659176 band -4758885413915764. +-4538818359625812 = 54281959185659176 bor -4758885413915764. +-58600710490995036 = 54281959185659176 bxor -4758885413915764. +-54281959185659177 = bnot(54281959185659176). +0 = 54281959185659176 bsl -78. +16405715499702717044095293200073169567744 = 54281959185659176 bsr -78. +75484079292225385591313 = 75491318149378877719244 + -7238857153492127931. +75498557006532369847175 = 75491318149378877719244 - -7238857153492127931. +-546470868412181397694378331179405548604164 = 75491318149378877719244 * -7238857153492127931. +-75491318149378877719244 = -(75491318149378877719244). +75491318149378877719244 = +(75491318149378877719244). +-10428 = 75491318149378877719244 div -7238857153492127931. +4515752762967654776 = 75491318149378877719244 rem -7238857153492127931. +75484079573734998934084 = 75491318149378877719244 band -7238857153492127931. +-281509613342771 = 75491318149378877719244 bor -7238857153492127931. +-75484079855244612276855 = 75491318149378877719244 bxor -7238857153492127931. +-75491318149378877719245 = bnot(75491318149378877719244). +38651554892481985392252928 = 75491318149378877719244 bsl 9. +147443980760505620545 = 75491318149378877719244 bsr 9. +846314546781048692419533467 = -44582885879577817 + 846314546825631578299111284. +-846314546870214464178689101 = -44582885879577817 - 846314546825631578299111284. +-37731144859353749299911077263371216220787028 = -44582885879577817 * 846314546825631578299111284. +44582885879577817 = -(-44582885879577817). +-44582885879577817 = +(-44582885879577817). +0 = -44582885879577817 div 846314546825631578299111284. +-44582885879577817 = -44582885879577817 rem 846314546825631578299111284. +846314546788968766774706980 = -44582885879577817 band 846314546825631578299111284. +-7920074355173513 = -44582885879577817 bor 846314546825631578299111284. +-846314546796888841129880493 = -44582885879577817 bxor 846314546825631578299111284. +44582885879577816 = bnot(-44582885879577817). +-1 = -44582885879577817 bsl -216. +-4695125881176098779573626983064072496921988771806705828324879944082052820250918912 = -44582885879577817 bsr -216. +-23378346714231806796 = -58913948147 + -23378346655317858649. +23378346596403910502 = -58913948147 - -23378346655317858649. +1377310702613987206250261473403 = -58913948147 * -23378346655317858649. +58913948147 = -(-58913948147). +-58913948147 = +(-58913948147). +0 = -58913948147 div -23378346655317858649. +-58913948147 = -58913948147 rem -23378346655317858649. +-23378346675274488315 = -58913948147 band -23378346655317858649. +-38957318481 = -58913948147 bor -23378346655317858649. +23378346636317169834 = -58913948147 bxor -23378346655317858649. +58913948146 = bnot(-58913948147). +-7540985362816 = -58913948147 bsl 7. +-460265220 = -58913948147 bsr 7. +-995879234083410706492793 = -84936519757496 + -995879233998474186735297. +995879233913537666977801 = -84936519757496 - -995879233998474186735297. +84586516234591384969560304166383536312 = -84936519757496 * -995879233998474186735297. +84936519757496 = -(-84936519757496). +-84936519757496 = +(-84936519757496). +0 = -84936519757496 div -995879233998474186735297. +-84936519757496 = -84936519757496 rem -995879233998474186735297. +-995879234069068735495928 = -84936519757496 band -995879233998474186735297. +-14341970996865 = -84936519757496 bor -995879233998474186735297. +995879234054726764499063 = -84936519757496 bxor -995879233998474186735297. +84936519757495 = bnot(-84936519757496). +-21234129939374 = -84936519757496 bsl -2. +-339746079029984 = -84936519757496 bsr -2. +9738893580548867195 = -42543967528973 + 9738936124516396168. +-9738978668483925141 = -42543967528973 - 9738936124516396168. +-414332982248167708124130086175464 = -42543967528973 * 9738936124516396168. +42543967528973 = -(-42543967528973). +-42543967528973 = +(-42543967528973). +0 = -42543967528973 div 9738936124516396168. +-42543967528973 = -42543967528973 rem 9738936124516396168. +9738893793318700160 = -42543967528973 band 9738936124516396168. +-212769832965 = -42543967528973 bor 9738936124516396168. +-9738894006088533125 = -42543967528973 bxor 9738936124516396168. +42543967528972 = bnot(-42543967528973). +-340351740231784 = -42543967528973 bsl 3. +-5317995941122 = -42543967528973 bsr 3. +-71223385482623257918611962250 = -71223385482623257918611962322 + 72. +-71223385482623257918611962394 = -71223385482623257918611962322 - 72. +-5128083754748874570140061287184 = -71223385482623257918611962322 * 72. +71223385482623257918611962322 = -(-71223385482623257918611962322). +-71223385482623257918611962322 = +(-71223385482623257918611962322). +-989213687258656359980721698 = -71223385482623257918611962322 div 72. +-66 = -71223385482623257918611962322 rem 72. +8 = -71223385482623257918611962322 band 72. +-71223385482623257918611962258 = -71223385482623257918611962322 bor 72. +-71223385482623257918611962266 = -71223385482623257918611962322 bxor 72. +71223385482623257918611962321 = bnot(-71223385482623257918611962322). +-176340561244792838116701740498131728651107744015770976256 = -71223385482623257918611962322 bsl 91. +-29 = -71223385482623257918611962322 bsr 91. +87477546472702745 = 87516898231171237 + -39351758468492. +87556249989639729 = 87516898231171237 - -39351758468492. +-3443943841104645261102521164604 = 87516898231171237 * -39351758468492. +-87516898231171237 = -(87516898231171237). +87516898231171237 = +(87516898231171237). +-2223 = 87516898231171237 div -39351758468492. +37939155713521 = 87516898231171237 rem -39351758468492. +87481705092876324 = 87516898231171237 band -39351758468492. +-4158620173579 = 87516898231171237 bor -39351758468492. +-87485863713049903 = 87516898231171237 bxor -39351758468492. +-87516898231171238 = bnot(87516898231171237). +0 = 87516898231171237 bsl -322. +747739840183165556231747713118623014305740385103595472270217127206668955381854797942139748885855913209911257858048 = 87516898231171237 bsr -322. +-2572165226296481 = -2572165226297448 + 967. +-2572165226298415 = -2572165226297448 - 967. +-2487283773829632216 = -2572165226297448 * 967. +2572165226297448 = -(-2572165226297448). +-2572165226297448 = +(-2572165226297448). +-2659943357081 = -2572165226297448 div 967. +-121 = -2572165226297448 rem 967. +896 = -2572165226297448 band 967. +-2572165226297377 = -2572165226297448 bor 967. +-2572165226298273 = -2572165226297448 bxor 967. +2572165226297447 = bnot(-2572165226297448). +-1 = -2572165226297448 bsl -277. +-624608171349100629421385803006244944484997667512182838365822583265372804924905146864213810642681856 = -2572165226297448 bsr -277. +-7256638636891165207778490262 = -7184166541211583221336 + -7256631452724623996195268926. +7256624268558082784612047590 = -7184166541211583221336 - -7256631452724623996195268926. +52132848884567848459087375659910565373045901005136 = -7184166541211583221336 * -7256631452724623996195268926. +7184166541211583221336 = -(-7184166541211583221336). +-7184166541211583221336 = +(-7184166541211583221336). +0 = -7184166541211583221336 div -7256631452724623996195268926. +-7184166541211583221336 = -7184166541211583221336 rem -7256631452724623996195268926. +-7256633891158678290607239040 = -7184166541211583221336 band -7256631452724623996195268926. +-4745732486917171251222 = -7184166541211583221336 bor -7256631452724623996195268926. +7256629145426191373435987818 = -7184166541211583221336 bxor -7256631452724623996195268926. +7184166541211583221335 = bnot(-7184166541211583221336). +-1 = -7184166541211583221336 bsl -351. +-32953752038621890334425178917985074997854170453384134811778334942985990684658696341917651315139497320317419007913299938092515328 = -7184166541211583221336 bsr -351. +-3462186111954578 = -67714158933844334 + 64251972821889756. +-131966131755734090 = -67714158933844334 - 64251972821889756. +-4350768299474489564409187813242504 = -67714158933844334 * 64251972821889756. +67714158933844334 = -(-67714158933844334). +-67714158933844334 = +(-67714158933844334). +-1 = -67714158933844334 div 64251972821889756. +-3462186111954578 = -67714158933844334 rem 64251972821889756. +1201027477574288 = -67714158933844334 band 64251972821889756. +-4663213589528866 = -67714158933844334 bor 64251972821889756. +-5864241067103154 = -67714158933844334 bxor 64251972821889756. +67714158933844333 = bnot(-67714158933844334). +-1 = -67714158933844334 bsl -374. +-2605540732319311553167826272165063781607477544645504809702612489304829956429336753861030327061751678134696824627057563959721721856 = -67714158933844334 bsr -374. +-9652719261564706635 = -9748574598338171976 + 95855336773465341. +-9844429935111637317 = -9748574598338171976 - 95855336773465341. +-934452901184955092352836156733483816 = -9748574598338171976 * 95855336773465341. +9748574598338171976 = -(-9748574598338171976). +-9748574598338171976 = +(-9748574598338171976). +-101 = -9748574598338171976 div 95855336773465341. +-67185584218172535 = -9748574598338171976 rem 95855336773465341. +5641634999967928 = -9748574598338171976 band 95855336773465341. +-9658360896564674563 = -9748574598338171976 bor 95855336773465341. +-9664002531564642491 = -9748574598338171976 bxor 95855336773465341. +9748574598338171975 = bnot(-9748574598338171976). +-93275643364251906664796184423084838717559727181712738294726887614128686525946534428737553711187915471796433618576288688299419188855051822432041930762382413770591440466736418794551446453706979125411803145109989230641152 = -9748574598338171976 bsl 661. +-1 = -9748574598338171976 bsr 661. +64322201122929545141550 = 64919146984647711792883 + -596945861718166651333. +65516092846365878444216 = 64919146984647711792883 - -596945861718166651333. +-38753216138758848495241667646258677771863039 = 64919146984647711792883 * -596945861718166651333. +-64919146984647711792883 = -(64919146984647711792883). +64919146984647711792883 = +(64919146984647711792883). +-108 = 64919146984647711792883 div -596945861718166651333. +448993919085713448919 = 64919146984647711792883 rem -596945861718166651333. +64323950833336603647539 = 64919146984647711792883 band -596945861718166651333. +-1749710407058505989 = 64919146984647711792883 bor -596945861718166651333. +-64325700543743662153528 = 64919146984647711792883 bxor -596945861718166651333. +-64919146984647711792884 = bnot(64919146984647711792883). +0 = 64919146984647711792883 bsl -342. +581609272502131059560435752570029234159994619290776929561934516217066618271246715576422981086520311125732738535288214055288832 = 64919146984647711792883 bsr -342. +-5251933002520669 = -5318314627357648 + 66381624836979. +-5384696252194627 = -5318314627357648 - 66381624836979. +-353038366358273161551528865392 = -5318314627357648 * 66381624836979. +5318314627357648 = -(-5318314627357648). +-5318314627357648 = +(-5318314627357648). +-80 = -5318314627357648 div 66381624836979. +-7784640399328 = -5318314627357648 rem 66381624836979. +26410307616816 = -5318314627357648 band 66381624836979. +-5278343310137485 = -5318314627357648 bor 66381624836979. +-5304753617754301 = -5318314627357648 bxor 66381624836979. +5318314627357647 = bnot(-5318314627357648). +-83098666052464 = -5318314627357648 bsl -6. +-340372136150889472 = -5318314627357648 bsr -6. +-57081174464 = 32783127 + -57113957591. +57146740718 = 32783127 - -57113957591. +-1872374125178367057 = 32783127 * -57113957591. +-32783127 = -(32783127). +32783127 = +(32783127). +0 = 32783127 div -57113957591. +32783127 = 32783127 rem -57113957591. +28584705 = 32783127 band -57113957591. +-57109759169 = 32783127 bor -57113957591. +-57138343874 = 32783127 bxor -57113957591. +-32783128 = bnot(32783127). +0 = 32783127 bsl -335. +2294557385324912875494980346220154405065163305775677015722414843609744103577089254776917819792648174080884736 = 32783127 bsr -335. +-614181602134994308355643270 = -614181598438261869879976828 + -3696732438475666442. +-614181594741529431404310386 = -614181598438261869879976828 - -3696732438475666442. +2270465038061558370394846287066022208817205976 = -614181598438261869879976828 * -3696732438475666442. +614181598438261869879976828 = -(-614181598438261869879976828). +-614181598438261869879976828 = +(-614181598438261869879976828). +166141750 = -614181598438261869879976828 div -3696732438475666442. +-1828147314789823328 = -614181598438261869879976828 rem -3696732438475666442. +-614181599683582487689394044 = -614181598438261869879976828 band -3696732438475666442. +-2451411820666249226 = -614181598438261869879976828 bor -3696732438475666442. +614181597232170667023144818 = -614181598438261869879976828 bxor -3696732438475666442. +614181598438261869879976827 = bnot(-614181598438261869879976828). +-4798293737798920858437319 = -614181598438261869879976828 bsl -7. +-78615244600097519344637033984 = -614181598438261869879976828 bsr -7. +-3462738347991127928203 = -456319 + -3462738347991127471884. +3462738347991127015565 = -456319 - -3462738347991127471884. +1580113300216963296842634996 = -456319 * -3462738347991127471884. +456319 = -(-456319). +-456319 = +(-456319). +0 = -456319 div -3462738347991127471884. +-456319 = -456319 rem -3462738347991127471884. +-3462738347991127488384 = -456319 band -3462738347991127471884. +-439819 = -456319 bor -3462738347991127471884. +3462738347991127048565 = -456319 bxor -3462738347991127471884. +456318 = bnot(-456319). +-1 = -456319 bsl -394. +-18411401283105313136299990322644412116910265901219350689865213233082371597360983704565705280678737735984373430178627553591296 = -456319 bsr -394. +7848387228643692381463657 = 7848387228643692381462858 + 799. +7848387228643692381462059 = 7848387228643692381462858 - 799. +6270861395686310212788823542 = 7848387228643692381462858 * 799. +-7848387228643692381462858 = -(7848387228643692381462858). +7848387228643692381462858 = +(7848387228643692381462858). +9822762488915760177049 = 7848387228643692381462858 div 799. +707 = 7848387228643692381462858 rem 799. +266 = 7848387228643692381462858 band 799. +7848387228643692381463391 = 7848387228643692381462858 bor 799. +7848387228643692381463125 = 7848387228643692381462858 bxor 799. +-7848387228643692381462859 = bnot(7848387228643692381462858). +13941536331 = 7848387228643692381462858 bsl -49. +4418249224797386599965305306964553629696 = 7848387228643692381462858 bsr -49. +-5549579159671479070701 = -92853964 + -5549579159671386216737. +5549579159671293362773 = -92853964 - -5549579159671386216737. +515300423507277147598993595468 = -92853964 * -5549579159671386216737. +92853964 = -(-92853964). +-92853964 = +(-92853964). +0 = -92853964 div -5549579159671386216737. +-92853964 = -92853964 rem -5549579159671386216737. +-5549579159671453376492 = -92853964 band -5549579159671386216737. +-25694209 = -92853964 bor -5549579159671386216737. +5549579159671427682283 = -92853964 bxor -5549579159671386216737. +92853963 = bnot(-92853964). +-1 = -92853964 bsl -735. +-16782136989272980093816490385033612560449506270868835380490349714294723959512373280455297308712315539869175004841888273922635762863717436251445878139037165327133779761272117074039733622046904552059825139314096655650358806553034752 = -92853964 bsr -735. +7873498039473 = 7873498115865 + -76392. +7873498192257 = 7873498115865 - -76392. +-601472268067159080 = 7873498115865 * -76392. +-7873498115865 = -(7873498115865). +7873498115865 = +(7873498115865). +-103067050 = 7873498115865 div -76392. +32265 = 7873498115865 rem -76392. +7873498105112 = 7873498115865 band -76392. +-65639 = 7873498115865 bor -76392. +-7873498170751 = 7873498115865 bxor -76392. +-7873498115866 = bnot(7873498115865). +1082125341208249400033280 = 7873498115865 bsl 37. +57 = 7873498115865 bsr 37. +-467100769590 = -628469971 + -466472299619. +465843829648 = -628469971 - -466472299619. +293163832613856241049 = -628469971 * -466472299619. +628469971 = -(-628469971). +-628469971 = +(-628469971). +0 = -628469971 div -466472299619. +-628469971 = -628469971 rem -466472299619. +-467077692659 = -628469971 band -466472299619. +-23076931 = -628469971 bor -466472299619. +467054615728 = -628469971 bxor -466472299619. +628469970 = bnot(-628469971). +-5398515943926136832 = -628469971 bsl 33. +-1 = -628469971 bsr 33. +-7456232186824215298555595 = -97 + -7456232186824215298555498. +7456232186824215298555401 = -97 - -7456232186824215298555498. +723254522121948883959883306 = -97 * -7456232186824215298555498. +97 = -(-97). +-97 = +(-97). +0 = -97 div -7456232186824215298555498. +-97 = -97 rem -7456232186824215298555498. +-7456232186824215298555498 = -97 band -7456232186824215298555498. +-97 = -97 bor -7456232186824215298555498. +7456232186824215298555401 = -97 bxor -7456232186824215298555498. +96 = bnot(-97). +-1 = -97 bsl -778. +-154208517072044817110477834630003453808555974308167240991219760833051589028432443365473490592131797361866045314684635239422610702621836283873378166455290440194900103858198979418496750291215410327603723183913469408088684692295841394720768 = -97 bsr -778. +-66178579725227678922255570214 = 45732325748 + -66178579725227678967987895962. +66178579725227679013720221710 = 45732325748 - -66178579725227678967987895962. +-3026500365534100548029990922255317829576 = 45732325748 * -66178579725227678967987895962. +-45732325748 = -(45732325748). +45732325748 = +(45732325748). +0 = 45732325748 div -66178579725227678967987895962. +45732325748 = 45732325748 rem -66178579725227678967987895962. +8590524772 = 45732325748 band -66178579725227678967987895962. +-66178579725227678930846094986 = 45732325748 bor -66178579725227678967987895962. +-66178579725227678939436619758 = 45732325748 bxor -66178579725227678967987895962. +-45732325749 = bnot(45732325748). +5716540718 = 45732325748 bsl -3. +365858605984 = 45732325748 bsr -3. +-37712225963798 = -37712225963791 + -7. +-37712225963784 = -37712225963791 - -7. +263985581746537 = -37712225963791 * -7. +37712225963791 = -(-37712225963791). +-37712225963791 = +(-37712225963791). +5387460851970 = -37712225963791 div -7. +-1 = -37712225963791 rem -7. +-37712225963791 = -37712225963791 band -7. +-7 = -37712225963791 bor -7. +37712225963784 = -37712225963791 bxor -7. +37712225963790 = bnot(-37712225963791). +-5061649286682638286848 = -37712225963791 bsl 27. +-280978 = -37712225963791 bsr 27. +-40228549198831930 = 4349648727446694 + -44578197926278624. +48927846653725318 = 4349648727446694 - -44578197926278624. +-193899501881904670273392751669056 = 4349648727446694 * -44578197926278624. +-4349648727446694 = -(4349648727446694). +4349648727446694 = +(4349648727446694). +0 = 4349648727446694 div -44578197926278624. +4349648727446694 = 4349648727446694 rem -44578197926278624. +317041655414816 = 4349648727446694 band -44578197926278624. +-40545590854246746 = 4349648727446694 bor -44578197926278624. +-40862632509661562 = 4349648727446694 bxor -44578197926278624. +-4349648727446695 = bnot(4349648727446694). +6752908344513747637690457064417473670326630538753659067616117393202915830263445258130617408615993113903675936677510161499392289297220214035812746737076986874754312746973700128193439161869643768009306177595926894863094335723318300478027259459928064 = 4349648727446694 bsl 768. +0 = 4349648727446694 bsr 768. +848583217115039357 = 848583134997193418 + 82117845939. +848583052879347479 = 848583134997193418 - 82117845939. +69683819146133168296708829502 = 848583134997193418 * 82117845939. +-848583134997193418 = -(848583134997193418). +848583134997193418 = +(848583134997193418). +10333723 = 848583134997193418 div 82117845939. +61706892521 = 848583134997193418 rem 82117845939. +73056395906 = 848583134997193418 band 82117845939. +848583144058643451 = 848583134997193418 bor 82117845939. +848583071002247545 = 848583134997193418 bxor 82117845939. +-848583134997193419 = bnot(848583134997193418). +5 = 848583134997193418 bsl -57. +122293718098119922577138408275050496 = 848583134997193418 bsr -57. +-569568392787 = -569568392782 + -5. +-569568392777 = -569568392782 - -5. +2847841963910 = -569568392782 * -5. +569568392782 = -(-569568392782). +-569568392782 = +(-569568392782). +113913678556 = -569568392782 div -5. +-2 = -569568392782 rem -5. +-569568392782 = -569568392782 band -5. +-5 = -569568392782 bor -5. +569568392777 = -569568392782 bxor -5. +569568392781 = bnot(-569568392782). +-9113094284512 = -569568392782 bsl 4. +-35598024549 = -569568392782 bsr 4. +65335161399831779703913704 = 57185822923562963328294152 + 8149338476268816375619552. +49036484447294146952674600 = 57185822923562963328294152 - 8149338476268816375619552. +466026627048086949714978241189501601930310298459904 = 57185822923562963328294152 * 8149338476268816375619552. +-57185822923562963328294152 = -(57185822923562963328294152). +57185822923562963328294152 = +(57185822923562963328294152). +7 = 57185822923562963328294152 div 8149338476268816375619552. +140453589681248698957288 = 57185822923562963328294152 rem 8149338476268816375619552. +7317611534847486666611968 = 57185822923562963328294152 band 8149338476268816375619552. +58017549864984293037301736 = 57185822923562963328294152 bor 8149338476268816375619552. +50699938330136806370689768 = 57185822923562963328294152 bxor 8149338476268816375619552. +-57185822923562963328294153 = bnot(57185822923562963328294152). +29279141336864237224086605824 = 57185822923562963328294152 bsl 9. +111691060397583912750574 = 57185822923562963328294152 bsr 9. +499824736561663365 = -2773 + 499824736561666138. +-499824736561668911 = -2773 - 499824736561666138. +-1386013994485500200674 = -2773 * 499824736561666138. +2773 = -(-2773). +-2773 = +(-2773). +0 = -2773 div 499824736561666138. +-2773 = -2773 rem 499824736561666138. +499824736561664010 = -2773 band 499824736561666138. +-645 = -2773 bor 499824736561666138. +-499824736561664655 = -2773 bxor 499824736561666138. +2772 = bnot(-2773). +-790727989541646708830748053912931740245557665662516042968506303258418127416853899548806014111441930724135945277973580717033736137023380598072164364974356246501423827000063419161238133443739516928 = -2773 bsl 636. +-1 = -2773 bsr 636. +-5636784153952403932489085934 = -5636784153952933259926817425 + 529327437731491. +-5636784153953462587364548916 = -5636784153952933259926817425 - 529327437731491. +-2983704513257376458668302178379317330030675 = -5636784153952933259926817425 * 529327437731491. +5636784153952933259926817425 = -(-5636784153952933259926817425). +-5636784153952933259926817425 = +(-5636784153952933259926817425). +-10648955168676 = -5636784153952933259926817425 div 529327437731491. +-148631224841509 = -5636784153952933259926817425 rem 529327437731491. +423630351897635 = -5636784153952933259926817425 band 529327437731491. +-5636784153952827562840983569 = -5636784153952933259926817425 bor 529327437731491. +-5636784153953251193192881204 = -5636784153952933259926817425 bxor 529327437731491. +5636784153952933259926817424 = bnot(-5636784153952933259926817425). +-3098854860267376316756012568798455398400 = -5636784153952933259926817425 bsl 39. +-10253250646115582 = -5636784153952933259926817425 bsr 39. +56279753385219477533778544977 = -94599 + 56279753385219477533778639576. +-56279753385219477533778734175 = -94599 - 56279753385219477533778639576. +-5324008390488377355217925525250024 = -94599 * 56279753385219477533778639576. +94599 = -(-94599). +-94599 = +(-94599). +0 = -94599 div 56279753385219477533778639576. +-94599 = -94599 rem 56279753385219477533778639576. +56279753385219477533778545240 = -94599 band 56279753385219477533778639576. +-263 = -94599 bor 56279753385219477533778639576. +-56279753385219477533778545503 = -94599 bxor 56279753385219477533778639576. +94598 = bnot(-94599). +-1 = -94599 bsl -222. +-637595998691445843483926240054242510523850056306978904034980106491396096 = -94599 bsr -222. +617541146396428695254820 = 9829596 + 617541146396428685425224. +-617541146396428675595628 = 9829596 - 617541146396428685425224. +6070179982453749820541040129504 = 9829596 * 617541146396428685425224. +-9829596 = -(9829596). +9829596 = +(9829596). +0 = 9829596 div 617541146396428685425224. +9829596 = 9829596 rem 617541146396428685425224. +14408 = 9829596 band 617541146396428685425224. +617541146396428695240412 = 9829596 bor 617541146396428685425224. +617541146396428695226004 = 9829596 bxor 617541146396428685425224. +-9829597 = bnot(9829596). +0 = 9829596 bsl -781. +125015045161014717203289441762288117900434356357580493144604519274682108643919458274266784431377843036784250025653017056568044245117426098854979177853711924930146744848176268478031998571177718143882247174738400267205847645084736774447973793792 = 9829596 bsr -781. +660109205356653082434571 = 8611421642786154821912 + 651497783713866927612659. +-642886362071080772790747 = 8611421642786154821912 - 651497783713866927612659. +5610322114900806920083336854208274531461784008 = 8611421642786154821912 * 651497783713866927612659. +-8611421642786154821912 = -(8611421642786154821912). +8611421642786154821912 = +(8611421642786154821912). +0 = 8611421642786154821912 div 651497783713866927612659. +8611421642786154821912 = 8611421642786154821912 rem 651497783713866927612659. +8573375208632380563472 = 8611421642786154821912 band 651497783713866927612659. +651535830148020701871099 = 8611421642786154821912 bor 651497783713866927612659. +642962454939388321307627 = 8611421642786154821912 bxor 651497783713866927612659. +-8611421642786154821913 = bnot(8611421642786154821912). +1301321245944051079661665054096505666025816064 = 8611421642786154821912 bsl 77. +0 = 8611421642786154821912 bsr 77. +377194245837736757882924482170 = 377194245837736846762764359958 + -88879839877788. +377194245837736935642604237746 = 377194245837736846762764359958 - -88879839877788. +-33524964172881053730057518754198488760812904 = 377194245837736846762764359958 * -88879839877788. +-377194245837736846762764359958 = -(377194245837736846762764359958). +377194245837736846762764359958 = +(377194245837736846762764359958). +-4243867297200223 = 377194245837736846762764359958 div -88879839877788. +88683878013234 = 377194245837736846762764359958 rem -88879839877788. +377194245837736828345893732612 = 377194245837736846762764359958 band -88879839877788. +-70462969250442 = 377194245837736846762764359958 bor -88879839877788. +-377194245837736898808862983054 = 377194245837736846762764359958 bxor -88879839877788. +-377194245837736846762764359959 = bnot(377194245837736846762764359958). +12070215866807579096408459518656 = 377194245837736846762764359958 bsl 5. +11787320182429276461336386248 = 377194245837736846762764359958 bsr 5. +-4741322768177 = -4741322797952 + 29775. +-4741322827727 = -4741322797952 - 29775. +-141172886309020800 = -4741322797952 * 29775. +4741322797952 = -(-4741322797952). +-4741322797952 = +(-4741322797952). +-159238381 = -4741322797952 div 29775. +-3677 = -4741322797952 rem 29775. +1024 = -4741322797952 band 29775. +-4741322769201 = -4741322797952 bor 29775. +-4741322770225 = -4741322797952 bxor 29775. +4741322797951 = bnot(-4741322797952). +-2427557272551424 = -4741322797952 bsl 9. +-9260396090 = -4741322797952 bsr 9. +99364986943748632704689 = 99364986943748642619248 + -9914559. +99364986943748652533807 = 99364986943748642619248 - -9914559. +-985160025588025598418448831632 = 99364986943748642619248 * -9914559. +-99364986943748642619248 = -(99364986943748642619248). +99364986943748642619248 = +(99364986943748642619248). +-10022128764753797 = 99364986943748642619248 div -9914559. +1788725 = 99364986943748642619248 rem -9914559. +99364986943748641437504 = 99364986943748642619248 band -9914559. +-8732815 = 99364986943748642619248 bor -9914559. +-99364986943748650170319 = 99364986943748642619248 bxor -9914559. +-99364986943748642619249 = bnot(99364986943748642619248). +3179679582199956563815936 = 99364986943748642619248 bsl 5. +3105155841992145081851 = 99364986943748642619248 bsr 5. +8667485381021 = 8667485389556 + -8535. +8667485398091 = 8667485389556 - -8535. +-73976987799860460 = 8667485389556 * -8535. +-8667485389556 = -(8667485389556). +8667485389556 = +(8667485389556). +-1015522599 = 8667485389556 div -8535. +7091 = 8667485389556 rem -8535. +8667485389472 = 8667485389556 band -8535. +-8451 = 8667485389556 bor -8535. +-8667485397923 = 8667485389556 bxor -8535. +-8667485389557 = bnot(8667485389556). +277359532465792 = 8667485389556 bsl 5. +270858918423 = 8667485389556 bsr 5. +6134725647932282021187 = 6134686373166524876423 + 39274765757144764. +6134647098400767731659 = 6134686373166524876423 - 39274765757144764. +240938370299663236613351775854421499172 = 6134686373166524876423 * 39274765757144764. +-6134686373166524876423 = -(6134686373166524876423). +6134686373166524876423 = +(6134686373166524876423). +156199 = 6134686373166524876423 div 39274765757144764. +7236666269884387 = 6134686373166524876423 rem 39274765757144764. +36028938685990532 = 6134686373166524876423 band 39274765757144764. +6134689618993596030655 = 6134686373166524876423 bor 39274765757144764. +6134653590054910040123 = 6134686373166524876423 bxor 39274765757144764. +-6134686373166524876424 = bnot(6134686373166524876423). +1533671593291631219105 = 6134686373166524876423 bsl -2. +24538745492666099505692 = 6134686373166524876423 bsr -2. +796190 = 796128 + 62. +796066 = 796128 - 62. +49359936 = 796128 * 62. +-796128 = -(796128). +796128 = +(796128). +12840 = 796128 div 62. +48 = 796128 rem 62. +32 = 796128 band 62. +796158 = 796128 bor 62. +796126 = 796128 bxor 62. +-796129 = bnot(796128). +458936545809819934654464 = 796128 bsl 59. +0 = 796128 bsr 59. +-4853967239688694934843182549 = -4853967239688771551186895246 + 76616343712697. +-4853967239688848167530607943 = -4853967239688771551186895246 - 76616343712697. +-371893222406166024238845641488852059138462 = -4853967239688771551186895246 * 76616343712697. +4853967239688771551186895246 = -(-4853967239688771551186895246). +-4853967239688771551186895246 = +(-4853967239688771551186895246). +-63354201002995 = -4853967239688771551186895246 div 76616343712697. +-13611670367731 = -4853967239688771551186895246 rem 76616343712697. +1142467605040 = -4853967239688771551186895246 band 76616343712697. +-4853967239688696077310787589 = -4853967239688771551186895246 bor 76616343712697. +-4853967239688697219778392629 = -4853967239688771551186895246 bxor 76616343712697. +4853967239688771551186895245 = bnot(-4853967239688771551186895246). +-1 = -4853967239688771551186895246 bsl -666. +-1486188693811800700044646223823865461549051074643879329904045362554983936403642602692697466395741062471646174962499126670468038568597407402903708616589970221885698780048932809206830445140876586892595078611386751158397833675014144 = -4853967239688771551186895246 bsr -666. +-374855932158674925467 = 797 + -374855932158674926264. +374855932158674927061 = 797 - -374855932158674926264. +-298760177930463916232408 = 797 * -374855932158674926264. +-797 = -(797). +797 = +(797). +0 = 797 div -374855932158674926264. +797 = 797 rem -374855932158674926264. +264 = 797 band -374855932158674926264. +-374855932158674925731 = 797 bor -374855932158674926264. +-374855932158674925995 = 797 bxor -374855932158674926264. +-798 = bnot(797). +13371441152 = 797 bsl 24. +0 = 797 bsr 24. +-57766182273728 = 9255 + -57766182282983. +57766182292238 = 9255 - -57766182282983. +-534626017029007665 = 9255 * -57766182282983. +-9255 = -(9255). +9255 = +(9255). +0 = 9255 div -57766182282983. +9255 = 9255 rem -57766182282983. +1 = 9255 band -57766182282983. +-57766182273729 = 9255 bor -57766182282983. +-57766182273730 = 9255 bxor -57766182282983. +-9256 = bnot(9255). +2369280 = 9255 bsl 8. +36 = 9255 bsr 8. +43583457932098704125432925625 = 43583457926631745136214938829 + 5466958989217986796. +43583457921164786146996952033 = 43583457926631745136214938829 - 5466958989217986796. +238268977093203339917214546461418761963669701884 = 43583457926631745136214938829 * 5466958989217986796. +-43583457926631745136214938829 = -(43583457926631745136214938829). +43583457926631745136214938829 = +(43583457926631745136214938829). +7972157466 = 43583457926631745136214938829 div 5466958989217986796. +4421758198994119893 = 43583457926631745136214938829 rem 5466958989217986796. +5231643519462150348 = 43583457926631745136214938829 band 5466958989217986796. +43583457926867060605970775277 = 43583457926631745136214938829 bor 5466958989217986796. +43583457921635417086508624929 = 43583457926631745136214938829 bxor 5466958989217986796. +-43583457926631745136214938830 = bnot(43583457926631745136214938829). +9909731017303726 = 43583457926631745136214938829 bsl -42. +191682075076070720302541032957128229257216 = 43583457926631745136214938829 bsr -42. +688582391845697458364529253983 = 747334547 + 688582391845697458363781919436. +-688582391845697458363034584889 = 747334547 - 688582391845697458363781919436. +514601409882180803945348321968493555492 = 747334547 * 688582391845697458363781919436. +-747334547 = -(747334547). +747334547 = +(747334547). +0 = 747334547 div 688582391845697458363781919436. +747334547 = 747334547 rem 688582391845697458363781919436. +67641984 = 747334547 band 688582391845697458363781919436. +688582391845697458364461611999 = 747334547 bor 688582391845697458363781919436. +688582391845697458364393970015 = 747334547 bxor 688582391845697458363781919436. +-747334548 = bnot(747334547). +1459637 = 747334547 bsl -9. +382635288064 = 747334547 bsr -9. +4198468694770 = 4192924421877 + 5544272893. +4187380148984 = 4192924421877 - 5544272893. +23246717214610347280161 = 4192924421877 * 5544272893. +-4192924421877 = -(4192924421877). +4192924421877 = +(4192924421877). +756 = 4192924421877 div 5544272893. +1454114769 = 4192924421877 rem 5544272893. +138691317 = 4192924421877 band 5544272893. +4198330003453 = 4192924421877 bor 5544272893. +4198191312136 = 4192924421877 bxor 5544272893. +-4192924421878 = bnot(4192924421877). +8189305511 = 4192924421877 bsl -9. +2146777304001024 = 4192924421877 bsr -9. +695779499497740362954764 = -946965296458 + 695779499498687328251222. +-695779499499634293547680 = -946965296458 - 695779499498687328251222. +-658879040012173308179266399930771676 = -946965296458 * 695779499498687328251222. +946965296458 = -(-946965296458). +-946965296458 = +(-946965296458). +0 = -946965296458 div 695779499498687328251222. +-946965296458 = -946965296458 rem 695779499498687328251222. +695779499498394708101142 = -946965296458 band 695779499498687328251222. +-654345146378 = -946965296458 bor 695779499498687328251222. +-695779499499049053247520 = -946965296458 bxor 695779499498687328251222. +946965296457 = bnot(-946965296458). +-29592665515 = -946965296458 bsl -5. +-30302889486656 = -946965296458 bsr -5. +-8749549967799272686 = -5 + -8749549967799272681. +8749549967799272676 = -5 - -8749549967799272681. +43747749838996363405 = -5 * -8749549967799272681. +5 = -(-5). +-5 = +(-5). +0 = -5 div -8749549967799272681. +-5 = -5 rem -8749549967799272681. +-8749549967799272685 = -5 band -8749549967799272681. +-1 = -5 bor -8749549967799272681. +8749549967799272684 = -5 bxor -8749549967799272681. +4 = bnot(-5). +-160 = -5 bsl 5. +-1 = -5 bsr 5. +-4442553739 = -4442554356 + 617. +-4442554973 = -4442554356 - 617. +-2741056037652 = -4442554356 * 617. +4442554356 = -(-4442554356). +-4442554356 = +(-4442554356). +-7200250 = -4442554356 div 617. +-106 = -4442554356 rem 617. +8 = -4442554356 band 617. +-4442553747 = -4442554356 bor 617. +-4442553755 = -4442554356 bxor 617. +4442554355 = bnot(-4442554356). +-71080869696 = -4442554356 bsl 4. +-277659648 = -4442554356 bsr 4. +-80761627119765 = -47577995383167 + -33183631736598. +-14394363646569 = -47577995383167 - -33183631736598. +1578810677560573582627045866 = -47577995383167 * -33183631736598. +47577995383167 = -(-47577995383167). +-47577995383167 = +(-47577995383167). +1 = -47577995383167 div -33183631736598. +-14394363646569 = -47577995383167 rem -33183631736598. +-69749188329344 = -47577995383167 band -33183631736598. +-11012438790421 = -47577995383167 bor -33183631736598. +58736749538923 = -47577995383167 bxor -33183631736598. +47577995383166 = bnot(-47577995383167). +-6504062805347175992854226195333100911915243382216748635078916338179559855776585782654748012038802701462209036288 = -47577995383167 bsl 326. +-1 = -47577995383167 bsr 326. +7153697534725 = 7153697524993 + 9732. +7153697515261 = 7153697524993 - 9732. +69619784313231876 = 7153697524993 * 9732. +-7153697524993 = -(7153697524993). +7153697524993 = +(7153697524993). +735069618 = 7153697524993 div 9732. +2617 = 7153697524993 rem 9732. +1024 = 7153697524993 band 9732. +7153697533701 = 7153697524993 bor 9732. +7153697532677 = 7153697524993 bxor 9732. +-7153697524994 = bnot(7153697524993). +697876402438937479803173358990579965085580863789430026221840561487579144890078941736343300387089227788186901649794788881497645969466145766479590030808449024 = 7153697524993 bsl 475. +0 = 7153697524993 bsr 475. + +0 = 7153697524993 bsr 475833444444444444444444444444444444444444444444. +-1 = -83987348 bsr 475833444444444444444444444444444444444444444444. + diff --git a/erts/emulator/test/big_SUITE_data/eq_math.dat b/erts/emulator/test/big_SUITE_data/eq_math.dat new file mode 100644 index 0000000000..8422328906 --- /dev/null +++ b/erts/emulator/test/big_SUITE_data/eq_math.dat @@ -0,0 +1,78 @@ +1 = fac(1). +2 = fac(2). +6 = fac(3). +24 = fac(4). +120 = fac(5). +720 = fac(6). +5040 = fac(7). +40320 = fac(8). +362880 = fac(9). +3628800 = fac(10). +39916800 = fac(11). +479001600 = fac(12). +6227020800 = fac(13). +87178291200 = fac(14). +1307674368000 = fac(15). +20922789888000 = fac(16). +355687428096000 = fac(17). +6402373705728000 = fac(18). +121645100408832000 = fac(19). +2432902008176640000 = fac(20). +265252859812191058636308480000000 = fac(30). +815915283247897734345611269596115894272000000000 = fac(40). +30414093201713378043612608166064768844377641568960512000000000000 = fac(50). +8320987112741390144276341183223364380754172606361245952449277696409600000000000000 = fac(60). +11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000 = fac(70). +71569457046263802294811533723186532165584657342365752577109445058227039255480148842668944867280814080000000000000000000 = fac(80). +1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000 = fac(90). +93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000 = fac(100). +385620482362580421735677065923463640617493109590223590278828403276373402575165543560686168588507361534030051833058916347592172932262498857766114955245039357760034644709279247692495585280000000000000000000000000000000 = fac(128). +857817775342842654119082271681232625157781520279485619859655650377269452553147589377440291360451408450375885342336584306157196834693696475322289288497426025679637332563368786442675207626794560187968867971521143307702077526646451464709187326100832876325702818980773671781454170250523018608495319068138257481070252817559459476987034665712738139286205234756808218860701203611083152093501947437109101726968262861606263662435022840944191408424615936000000000000000000000000000000000000000000000000000000000000000 = fac(256). +402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 = fac(999). +2 = 1 bsl 1. +4 = 1 bsl 2. +8 = 1 bsl 3. +16 = 1 bsl 4. +32 = 1 bsl 5. +1024 = 1 bsl 10. +1048576 = 1 bsl 20. +134217728 = 1 bsl 27. +268435456 = 1 bsl 28. +1073741824 = 1 bsl 30. +2147483648 = 1 bsl 31. +4294967296 = 1 bsl 32. +1099511627776 = 1 bsl 40. +1125899906842624 = 1 bsl 50. +1152921504606846976 = 1 bsl 60. +1180591620717411303424 = 1 bsl 70. +1208925819614629174706176 = 1 bsl 80. +1237940039285380274899124224 = 1 bsl 90. +1267650600228229401496703205376 = 1 bsl 100. +3072 = 3 bsl 10. +3145728 = 3 bsl 20. +402653184 = 3 bsl 27. +805306368 = 3 bsl 28. +3221225472 = 3 bsl 30. +6442450944 = 3 bsl 31. +12884901888 = 3 bsl 32. +3298534883328 = 3 bsl 40. +3377699720527872 = 3 bsl 50. +3458764513820540928 = 3 bsl 60. +3541774862152233910272 = 3 bsl 70. +3626777458843887524118528 = 3 bsl 80. +3713820117856140824697372672 = 3 bsl 90. +3802951800684688204490109616128 = 3 bsl 100. +5120 = 5 bsl 10. +5242880 = 5 bsl 20. +671088640 = 5 bsl 27. +1342177280 = 5 bsl 28. +5368709120 = 5 bsl 30. +10737418240 = 5 bsl 31. +21474836480 = 5 bsl 32. +5497558138880 = 5 bsl 40. +5629499534213120 = 5 bsl 50. +5764607523034234880 = 5 bsl 60. +5902958103587056517120 = 5 bsl 70. +6044629098073145873530880 = 5 bsl 80. +6189700196426901374495621120 = 5 bsl 90. +6338253001141147007483516026880 = 5 bsl 100. diff --git a/erts/emulator/test/big_SUITE_data/literal_test.erl b/erts/emulator/test/big_SUITE_data/literal_test.erl new file mode 100644 index 0000000000..dc0adeb1ca --- /dev/null +++ b/erts/emulator/test/big_SUITE_data/literal_test.erl @@ -0,0 +1,38 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(literal_test). + +-export([t/0]). + +t() -> + 2639222 = do_band(-30710410, 11032439), + -104896167137483835127591520601167100453480347078199925156632915223228188306305878154109985624943277357501787279310034030156370067160844817777591157023073455111626047495778039507502639061242015835277440456218702874565483838389693116456108032 = do_bsl(-283388912239613, 746), + 899396154689163167548626101 = do_plus(899396154689163167641847368, -93221267), + ok. + +do_plus(A, B) -> + A + B. + +do_band(A, B) -> + A band B. + +do_bsl(X, S) -> + X bsl S. + diff --git a/erts/emulator/test/big_SUITE_data/negative.dat b/erts/emulator/test/big_SUITE_data/negative.dat new file mode 100644 index 0000000000..6169bd25ce --- /dev/null +++ b/erts/emulator/test/big_SUITE_data/negative.dat @@ -0,0 +1,10 @@ +%% 'bor' operations. +(-1 bsl 28) bor 0 = -1 bsl 28. +0 bor (-1 bsl 28) = -1 bsl 28. +(-1 bsl 28) bor (-1 bsl 28) = -1 bsl 28. + +%%(-1 bsl 28) bor -16#FFFFffff = -16#10000001. Not sure about the result yet. + +%% 'band' operations. +(-1 bsl 28) band 16#FFFFffffFFFF = 16#FFFFf0000000. + diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl new file mode 100644 index 0000000000..e47dfa18f7 --- /dev/null +++ b/erts/emulator/test/binary_SUITE.erl @@ -0,0 +1,1313 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(binary_SUITE). +-compile({nowarn_deprecated_function, {erlang,hash,2}}). + +%% Tests binaries and the BIFs: +%% list_to_binary/1 +%% iolist_to_binary/1 +%% bitstr_to_list/1 +%% binary_to_list/1 +%% binary_to_list/3 +%% binary_to_term/1 +%% bitstr_to_list/1 +%% term_to_binary/1 +%% erlang:external_size/1 +%% size(Binary) +%% iolist_size/1 +%% concat_binary/1 +%% split_binary/2 +%% hash(Binary, N) +%% phash(Binary, N) +%% phash2(Binary, N) +%% + +-include("test_server.hrl"). + +-export([all/1, init_per_testcase/2, fin_per_testcase/2, + copy_terms/1, conversions/1, deep_lists/1, deep_bitstr_lists/1, + bad_list_to_binary/1, bad_binary_to_list/1, + t_split_binary/1, bad_split/1, t_concat_binary/1, + terms/1, terms_float/1, external_size/1, t_iolist_size/1, + t_hash/1, + bad_size/1, + bad_term_to_binary/1, + bad_binary_to_term_2/1, + bad_binary_to_term/1, bad_terms/1, more_bad_terms/1, + otp_5484/1,otp_5933/1, + ordering/1,unaligned_order/1,gc_test/1, + bit_sized_binary_sizes/1, + bitlevel_roundtrip/1, + otp_6817/1,deep/1,obsolete_funs/1,robustness/1,otp_8117/1, + otp_8180/1]). + +%% Internal exports. +-export([sleeper/0]). + +all(suite) -> + [copy_terms,conversions,deep_lists,deep_bitstr_lists, + t_split_binary, bad_split, t_concat_binary, + bad_list_to_binary, bad_binary_to_list, terms, terms_float, + external_size, t_iolist_size, + bad_binary_to_term_2, + bad_binary_to_term, bad_terms, t_hash, bad_size, bad_term_to_binary, + more_bad_terms, otp_5484, otp_5933, ordering, unaligned_order, + gc_test, bit_sized_binary_sizes, bitlevel_roundtrip, otp_6817, otp_8117, + deep,obsolete_funs,robustness,otp_8180]. + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog=?t:timetrap(?t:minutes(2)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +-define(heap_binary_size, 64). + +copy_terms(Config) when is_list(Config) -> + Self = self(), + ?line Pid = spawn_link(fun() -> copy_server(Self) end), + F = fun(Term) -> + Pid ! Term, + receive + Term -> ok; + Other -> + io:format("Sent: ~P\nGot back:~P", [Term,12,Other,12]), + ?t:fail(bad_term) + end + end, + ?line test_terms(F), + ok. + +copy_server(Parent) -> + receive + Term -> + Parent ! Term, + copy_server(Parent) + end. + +%% Tests list_to_binary/1, binary_to_list/1 and size/1, +%% using flat lists. + +conversions(suite) -> []; +conversions(Config) when is_list(Config) -> + ?line test_bin([]), + ?line test_bin([1]), + ?line test_bin([1, 2]), + ?line test_bin([1, 2, 3]), + ?line test_bin(lists:seq(0, ?heap_binary_size)), + ?line test_bin(lists:seq(0, ?heap_binary_size+1)), + ?line test_bin(lists:seq(0, 255)), + ?line test_bin(lists:duplicate(50000, $@)), + + %% Binary in list. + List = [1,2,3,4,5], + ?line B1 = make_sub_binary(list_to_binary(List)), + ?line 5 = size(B1), + ?line 5 = size(make_unaligned_sub_binary(B1)), + ?line 40 = bit_size(B1), + ?line 40 = bit_size(make_unaligned_sub_binary(B1)), + ?line B2 = list_to_binary([42,B1,19]), + ?line B2 = list_to_binary([42,make_unaligned_sub_binary(B1),19]), + ?line B2 = iolist_to_binary(B2), + ?line B2 = iolist_to_binary(make_unaligned_sub_binary(B2)), + ?line 7 = size(B2), + ?line 7 = size(make_sub_binary(B2)), + ?line 56 = bit_size(B2), + ?line 56 = bit_size(make_sub_binary(B2)), + ?line [42,1,2,3,4,5,19] = binary_to_list(B2), + ?line [42,1,2,3,4,5,19] = binary_to_list(make_sub_binary(B2)), + ?line [42,1,2,3,4,5,19] = binary_to_list(make_unaligned_sub_binary(B2)), + ?line [42,1,2,3,4,5,19] = bitstring_to_list(B2), + ?line [42,1,2,3,4,5,19] = bitstring_to_list(make_sub_binary(B2)), + ?line [42,1,2,3,4,5,19] = bitstring_to_list(make_unaligned_sub_binary(B2)), + + ok. + +test_bin(List) -> + ?line Size = length(List), + ?line Bin = list_to_binary(List), + ?line Bin = iolist_to_binary(List), + ?line Bin = list_to_bitstring(List), + ?line Size = iolist_size(List), + ?line Size = iolist_size(Bin), + ?line Size = iolist_size(make_unaligned_sub_binary(Bin)), + ?line Size = size(Bin), + ?line Size = size(make_sub_binary(Bin)), + ?line Size = size(make_unaligned_sub_binary(Bin)), + ?line List = binary_to_list(Bin), + ?line List = binary_to_list(make_sub_binary(Bin)), + ?line List = binary_to_list(make_unaligned_sub_binary(Bin)), + ?line List = bitstring_to_list(Bin), + ?line List = bitstring_to_list(make_unaligned_sub_binary(Bin)). + +%% Tests list_to_binary/1, iolist_to_binary/1, list_to_bitstr/1, binary_to_list/1,3, +%% bitstr_to_list/1, and size/1, using deep lists. + +deep_lists(Config) when is_list(Config) -> + ?line test_deep_list(["abc"]), + ?line test_deep_list([[12,13,[123,15]]]), + ?line test_deep_list([[12,13,[lists:seq(0, 255), []]]]), + ok. + +test_deep_list(List) -> + ?line FlatList = lists:flatten(List), + ?line Size = length(FlatList), + ?line Bin = list_to_binary(List), + ?line Bin = iolist_to_binary(List), + ?line Bin = iolist_to_binary(Bin), + ?line Bin = list_to_bitstring(List), + ?line Size = size(Bin), + ?line Size = iolist_size(List), + ?line Size = iolist_size(FlatList), + ?line Size = iolist_size(Bin), + ?line Bitsize = bit_size(Bin), + ?line Bitsize = 8*Size, + ?line FlatList = binary_to_list(Bin), + ?line FlatList = bitstring_to_list(Bin), + io:format("testing plain binary..."), + ?line t_binary_to_list_3(FlatList, Bin, 1, Size), + io:format("testing unaligned sub binary..."), + ?line t_binary_to_list_3(FlatList, make_unaligned_sub_binary(Bin), 1, Size). + +t_binary_to_list_3(List, Bin, From, To) -> + ?line going_up(List, Bin, From, To), + ?line going_down(List, Bin, From, To), + ?line going_center(List, Bin, From, To). + +going_up(List, Bin, From, To) when From =< To -> + ?line List = binary_to_list(Bin, From, To), + ?line going_up(tl(List), Bin, From+1, To); +going_up(_List, _Bin, From, To) when From > To -> + ok. + +going_down(List, Bin, From, To) when To > 0-> + ?line compare(List, binary_to_list(Bin, From, To), To-From+1), + ?line going_down(List, Bin, From, To-1); +going_down(_List, _Bin, _From, _To) -> + ok. + +going_center(List, Bin, From, To) when From >= To -> + ?line compare(List, binary_to_list(Bin, From, To), To-From+1), + ?line going_center(tl(List), Bin, From+1, To-1); +going_center(_List, _Bin, _From, _To) -> + ok. + +compare([X|Rest1], [X|Rest2], Left) when Left > 0 -> + ?line compare(Rest1, Rest2, Left-1); +compare([_X|_], [_Y|_], _Left) -> + ?line test_server:fail(); +compare(_List, [], 0) -> + ok. + +deep_bitstr_lists(Config) when is_list(Config) -> + ?line {<<7:3>>,[<<7:3>>]} = test_deep_bitstr([<<7:3>>]), + ?line {<<42,5:3>>=Bin,[42,<<5:3>>]=List} = test_deep_bitstr([42,<<5:3>>]), + ?line {Bin,List} = test_deep_bitstr([42|<<5:3>>]), + ?line {Bin,List} = test_deep_bitstr([<<42,5:3>>]), + ?line {Bin,List} = test_deep_bitstr([<<1:3>>,<<10:5>>|<<5:3>>]), + ?line {Bin,List} = test_deep_bitstr([<<1:3>>,<<10:5>>,<<5:3>>]), + ?line {Bin,List} = test_deep_bitstr([[<<1:3>>,<<10:5>>],[],<<5:3>>]), + ?line {Bin,List} = test_deep_bitstr([[[<<1:3>>]|<<10:5>>],[],<<5:3>>]), + ?line {Bin,List} = test_deep_bitstr([[<<0:1>>,<<0:1>>,[],<<1:1>>,<<10:5>>], + <<1:1>>,<<0:1>>,<<1:1>>]), + ok. + +test_deep_bitstr(List) -> + %%?line {'EXIT',{badarg,_}} = list_to_binary(List), + Bin = list_to_bitstring(List), + {Bin,bitstring_to_list(Bin)}. + +bad_list_to_binary(suite) -> []; +bad_list_to_binary(Config) when is_list(Config) -> + ?line test_bad_bin(atom), + ?line test_bad_bin(42), + ?line test_bad_bin([1|2]), + ?line test_bad_bin([256]), + ?line test_bad_bin([255, [256]]), + ?line test_bad_bin([-1]), + ?line test_bad_bin([atom_in_list]), + ?line test_bad_bin([[<<8>>]|bad_tail]), + + {'EXIT',{badarg,_}} = (catch list_to_binary(id(<<1,2,3>>))), + {'EXIT',{badarg,_}} = (catch list_to_binary(id([<<42:7>>]))), + {'EXIT',{badarg,_}} = (catch list_to_bitstring(id(<<1,2,3>>))), + + %% Funs used to be implemented as a type of binary internally. + ?line test_bad_bin(fun(X, Y) -> X*Y end), + ?line test_bad_bin([1,fun(X) -> X + 1 end,2|fun() -> 0 end]), + ?line test_bad_bin([fun(X) -> X + 1 end]), + ok. + +test_bad_bin(List) -> + {'EXIT',{badarg,_}} = (catch list_to_binary(List)), + {'EXIT',{badarg,_}} = (catch iolist_to_binary(List)), + {'EXIT',{badarg,_}} = (catch list_to_bitstring(List)). + +bad_binary_to_list(doc) -> "Tries binary_to_list/1,3 with bad arguments."; +bad_binary_to_list(Config) when is_list(Config) -> + ?line bad_bin_to_list(fun(X) -> X * 42 end), + + GoodBin = list_to_binary(lists:seq(1, 10)), + ?line bad_bin_to_list(fun(X) -> X * 44 end, 1, 2), + ?line bad_bin_to_list(GoodBin, 0, 1), + ?line bad_bin_to_list(GoodBin, 2, 1), + ?line bad_bin_to_list(GoodBin, 11, 11), + {'EXIT',{badarg,_}} = (catch binary_to_list(id(<<42:7>>))), + ok. + +bad_bin_to_list(BadBin) -> + {'EXIT',{badarg,_}} = (catch binary_to_list(BadBin)), + {'EXIT',{badarg,_}} = (catch bitstring_to_list(BadBin)). + +bad_bin_to_list(Bin, First, Last) -> + {'EXIT',{badarg,_}} = (catch binary_to_list(Bin, First, Last)). + + +%% Tries to split a binary at all possible positions. + +t_split_binary(suite) -> []; +t_split_binary(Config) when is_list(Config) -> + ?line L = lists:seq(0, ?heap_binary_size-5), %Heap binary. + ?line B = list_to_binary(L), + ?line split(L, B, size(B)), + + %% Sub binary of heap binary. + ?line split(L, make_sub_binary(B), size(B)), + {X,_Y} = split_binary(B, size(B) div 2), + ?line split(binary_to_list(X), X, size(X)), + + %% Unaligned sub binary of heap binary. + ?line split(L, make_unaligned_sub_binary(B), size(B)), + {X,_Y} = split_binary(B, size(B) div 2), + ?line split(binary_to_list(X), X, size(X)), + + %% Reference-counted binary. + ?line L2 = lists:seq(0, ?heap_binary_size+1), + ?line B2 = list_to_binary(L2), + ?line split(L2, B2, size(B2)), + + %% Sub binary of reference-counted binary. + ?line split(L2, make_sub_binary(B2), size(B2)), + {X2,_Y2} = split_binary(B2, size(B2) div 2), + ?line split(binary_to_list(X2), X2, size(X2)), + + %% Unaligned sub binary of reference-counted binary. + ?line split(L2, make_unaligned_sub_binary(B2), size(B2)), + {X2,_Y2} = split_binary(B2, size(B2) div 2), + ?line split(binary_to_list(X2), X2, size(X2)), + + ok. + +split(L, B, Pos) when Pos > 0 -> + ?line {B1, B2} = split_binary(B, Pos), + ?line B1 = list_to_binary(lists:sublist(L, 1, Pos)), + ?line B2 = list_to_binary(lists:nthtail(Pos, L)), + ?line split(L, B, Pos-1); +split(_L, _B, 0) -> + ok. + +bad_split(doc) -> "Tries split_binary/2 with bad arguments."; +bad_split(suite) -> []; +bad_split(Config) when is_list(Config) -> + GoodBin = list_to_binary([1,2,3]), + ?line bad_split(GoodBin, -1), + ?line bad_split(GoodBin, 4), + ?line bad_split(GoodBin, a), + + %% Funs are a kind of binaries. + ?line bad_split(fun(_X) -> 1 end, 1), + ok. + +bad_split(Bin, Pos) -> + {'EXIT',{badarg,_}} = (catch split_binary(Bin, Pos)). + +%% Tests concat_binary/2 and size/1. + +t_concat_binary(suite) -> []; +t_concat_binary(Config) when is_list(Config) -> + test_concat([]), + + test_concat([[]]), + test_concat([[], []]), + test_concat([[], [], []]), + + test_concat([[1], []]), + test_concat([[], [2]]), + test_concat([[], [3], []]), + + test_concat([[1, 2, 3], [4, 5, 6, 7]]), + test_concat([[1, 2, 3], [4, 5, 6, 7], [9, 10]]), + + test_concat([lists:seq(0, 255), lists:duplicate(1024, $@), + lists:duplicate(2048, $a), + lists:duplicate(4000, $b)]), + ok. + +test_concat(Lists) -> + test_concat(Lists, 0, [], []). + +test_concat([List|Rest], Size, Combined, Binaries) -> + ?line Bin = list_to_binary(List), + ?line test_concat(Rest, Size+length(List), Combined++List, [Bin|Binaries]); +test_concat([], Size, Combined, Binaries0) -> + ?line Binaries = lists:reverse(Binaries0), + ?line Bin = concat_binary(Binaries), + ?line Size = size(Bin), + ?line Size = iolist_size(Bin), + ?line Combined = binary_to_list(Bin). + +t_hash(doc) -> "Test hash/2 with different type of binaries."; +t_hash(Config) when is_list(Config) -> + test_hash([]), + test_hash([253]), + test_hash(lists:seq(1, ?heap_binary_size)), + test_hash(lists:seq(1, ?heap_binary_size+1)), + test_hash([X rem 256 || X <- lists:seq(1, 312)]), + ok. + +test_hash(List) -> + Bin = list_to_binary(List), + Sbin = make_sub_binary(List), + Unaligned = make_unaligned_sub_binary(Sbin), + ?line test_hash_1(Bin, Sbin, Unaligned, fun erlang:hash/2), + ?line test_hash_1(Bin, Sbin, Unaligned, fun erlang:phash/2), + ?line test_hash_1(Bin, Sbin, Unaligned, fun erlang:phash2/2). + +test_hash_1(Bin, Sbin, Unaligned, Hash) when is_function(Hash, 2) -> + N = 65535, + case {Hash(Bin, N),Hash(Sbin, N),Hash(Unaligned, N)} of + {H,H,H} -> ok; + {H1,H2,H3} -> + io:format("Different hash values: ~p, ~p, ~p\n", [H1,H2,H3]), + ?t:fail() + end. + +bad_size(doc) -> "Try bad arguments to size/1."; +bad_size(suite) -> []; +bad_size(Config) when is_list(Config) -> + ?line {'EXIT',{badarg,_}} = (catch size(fun(X) -> X + 33 end)), + ok. + +bad_term_to_binary(Config) when is_list(Config) -> + T = id({a,b,c}), + ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, not_a_list)), + ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [blurf])), + ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,-1}])), + ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,10}])), + ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,cucumber}])), + ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed}])), + ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{version,1}|bad_tail])), + ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{minor_version,-1}])), + ?line {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{minor_version,x}])), + + ok. + +%% Tests binary_to_term/1 and term_to_binary/1. + +terms(Config) when is_list(Config) -> + TestFun = fun(Term) -> + try + S = io_lib:format("~p", [Term]), + io:put_chars(S) + catch + error:badarg -> + io:put_chars("bit sized binary") + end, + Bin = term_to_binary(Term), + case erlang:external_size(Bin) of + Sz when is_integer(Sz), size(Bin) =< Sz -> + ok + end, + Term = binary_to_term(Bin), + Unaligned = make_unaligned_sub_binary(Bin), + Term = binary_to_term(Unaligned), + BinC = erlang:term_to_binary(Term, [compressed]), + Term = binary_to_term(BinC), + true = size(BinC) =< size(Bin), + Bin = term_to_binary(Term, [{compressed,0}]), + terms_compression_levels(Term, size(Bin), 1), + UnalignedC = make_unaligned_sub_binary(BinC), + Term = binary_to_term(UnalignedC) + end, + ?line test_terms(TestFun), + ok. + +terms_compression_levels(Term, UncompressedSz, Level) when Level < 10 -> + BinC = erlang:term_to_binary(Term, [{compressed,Level}]), + Term = binary_to_term(BinC), + Sz = byte_size(BinC), + true = Sz =< UncompressedSz, + terms_compression_levels(Term, UncompressedSz, Level+1); +terms_compression_levels(_, _, _) -> ok. + +terms_float(Config) when is_list(Config) -> + ?line test_floats(fun(Term) -> + Bin0 = term_to_binary(Term), + Bin0 = term_to_binary(Term, [{minor_version,0}]), + Term = binary_to_term(Bin0), + Bin1 = term_to_binary(Term, [{minor_version,1}]), + Term = binary_to_term(Bin1), + true = size(Bin1) < size(Bin0) + end). + +external_size(Config) when is_list(Config) -> + %% Build a term whose external size only fits in a big num (on 32-bit CPU). + ?line external_size_1(16#11111111111111117777777777777777888889999, 0, 16#FFFFFFF), + + %% Test that the same binary aligned and unaligned has the same external size. + ?line Bin = iolist_to_binary([1,2,3,96]), + ?line Unaligned = make_unaligned_sub_binary(Bin), + case {erlang:external_size(Bin),erlang:external_size(Unaligned)} of + {X,X} -> ok; + {Sz1,Sz2} -> + io:format(" Aligned size: ~p\n", [Sz1]), + io:format("Unaligned size: ~p\n", [Sz2]), + ?line ?t:fail() + end. + +external_size_1(Term, Size0, Limit) when Size0 < Limit -> + case erlang:external_size(Term) of + Size when is_integer(Size), Size0 < Size -> + io:format("~p", [Size]), + external_size_1([Term|Term], Size, Limit) + end; +external_size_1(_, _, _) -> ok. + +t_iolist_size(Config) when is_list(Config) -> + %% Build a term whose external size only fits in a big num (on 32-bit CPU). + Bin = iolist_to_binary(lists:seq(0, 254)), + ?line ok = t_iolist_size_1(Bin, 0, 16#7FFFFFFF), + ?line ok = t_iolist_size_1(make_unaligned_sub_binary(Bin), 0, 16#7FFFFFFF). + +t_iolist_size_1(IOList, Size0, Limit) when Size0 < Limit -> + case iolist_size(IOList) of + Size when is_integer(Size), Size0 < Size -> + io:format("~p", [Size]), + t_iolist_size_1([IOList|IOList], Size, Limit) + end; +t_iolist_size_1(_, _, _) -> ok. + +bad_binary_to_term_2(doc) -> "OTP-4053."; +bad_binary_to_term_2(suite) -> []; +bad_binary_to_term_2(Config) when is_list(Config) -> + ?line {ok, N} = test_server:start_node(plopp, slave, []), + ?line R = rpc:call(N, erlang, binary_to_term, [<<131,111,255,255,255,0>>]), + ?line case R of + {badrpc, {'EXIT', _}} -> + ok; + _Other -> + test_server:fail({rpcresult, R}) + end, + ?line test_server:stop_node(N), + ok. + +bad_binary_to_term(doc) -> "Try bad input to binary_to_term/1."; +bad_binary_to_term(Config) when is_list(Config) -> + ?line bad_bin_to_term(an_atom), + ?line bad_bin_to_term({an,tuple}), + ?line bad_bin_to_term({a,list}), + ?line bad_bin_to_term(fun() -> self() end), + ?line bad_bin_to_term(fun(X) -> 42*X end), + ?line bad_bin_to_term(fun(X, Y) -> {X,Y} end), + ?line bad_bin_to_term(fun(X, Y, Z) -> {X,Y,Z} end), + ?line bad_bin_to_term(bit_sized_binary(term_to_binary({you,should,'not',see,this,term}))), + + %% Bad float. + ?line bad_bin_to_term(<<131,70,-1:64>>), + ok. + +bad_bin_to_term(BadBin) -> + {'EXIT',{badarg,_}} = (catch binary_to_term(BadBin)). + +%% Tests bad input to binary_to_term/1. + +bad_terms(suite) -> []; +bad_terms(Config) when is_list(Config) -> + ?line test_terms(fun corrupter/1). + +corrupter(Term) -> + ?line try + S = io_lib:format("About to corrupt: ~P", [Term,12]), + io:put_chars(S) + catch + error:badarg -> + io:format("About to corrupt: <<bit-level-binary:~p", + [bit_size(Term)]) + end, + ?line Bin = term_to_binary(Term), + ?line corrupter(Bin, size(Bin)-1), + ?line CompressedBin = term_to_binary(Term, [compressed]), + ?line corrupter(CompressedBin, size(CompressedBin)-1). + +corrupter(Bin, Pos) when Pos >= 0 -> + ?line {ShorterBin, _} = split_binary(Bin, Pos), + ?line catch binary_to_term(ShorterBin), %% emulator shouldn't crash + ?line MovedBin = list_to_binary([ShorterBin]), + ?line catch binary_to_term(MovedBin), %% emulator shouldn't crash + ?line corrupter(MovedBin, Pos-1); +corrupter(_Bin, _) -> + ok. + +more_bad_terms(suite) -> []; +more_bad_terms(Config) when is_list(Config) -> + ?line Data = ?config(data_dir, Config), + ?line BadFile = filename:join(Data, "bad_binary"), + ?line ok = io:format("File: ~s\n", [BadFile]), + ?line case file:read_file(BadFile) of + {ok,Bin} -> + ?line {'EXIT',{badarg,_}} = (catch binary_to_term(Bin)), + ok; + Other -> + ?line ?t:fail(Other) + end. + +otp_5484(Config) when is_list(Config) -> + ?line {'EXIT',_} = + (catch + binary_to_term( + <<131, + 104,2, %Tuple, 2 elements + 103, %Pid + 100,0,20,"wslin1427198@wslin14", + %% Obviously bad values follow. + 255,255,255,255, + 255,255,255,255, + 255, + 106>>)), + + ?line {'EXIT',_} = + (catch + binary_to_term( + <<131, + 104,2, %Tuple, 2 elements + 103, %Pid + 106, %[] instead of atom. + 0,0,0,17, + 0,0,0,135, + 2, + 106>>)), + + ?line {'EXIT',_} = + (catch + binary_to_term( + %% A old-type fun in a list containing a bad creator pid. + <<131,108,0,0,0,1,117,0,0,0,0,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,255,255,0,25,255,0,0,0,0,100,0,1,116,97,0,98,6,142,121,72,106>>)), + + ?line {'EXIT',_} = + (catch + binary_to_term( + %% A new-type fun in a list containing a bad creator pid. + %% + <<131, + 108,0,0,0,1, %List, 1 element + 112,0,0,0,66,0,52,216,81,158,148,250,237,109,185,9,208,60,202,156,244,218,0,0,0,0,0,0,0,0,100,0,1,116,97,0,98,6,142,121,72, + 103, %Pid. + 106, %[] instead of an atom. + 0,0,0,27,0,0,0,0,0,106>>)), + + ?line {'EXIT',_} = + (catch + binary_to_term( + %% A new-type fun in a list containing a bad module. + <<131, + 108,0,0,0,1, %List, 1 element + 112,0,0,0,70,0,224,90,4,101,48,28,110,228,153,48,239,169,232,77,108,145,0,0,0,0,0,0,0,2, + %%100,0,1,116, + 107,0,1,64, %String instead of atom (same length). + 97,0,98,6,64,82,230,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,0,0,0,48,0,0,0,0,0,97,42,97,7,106>>)), + + ?line {'EXIT',_} = + (catch + binary_to_term( + %% A new-type fun in a list containing a bad index. + <<131, + 108,0,0,0,1, %List, 1 element + 112,0,0,0,70,0,224,90,4,101,48,28,110,228,153,48,239,169,232,77,108,145,0,0,0,0,0,0,0,2, + 100,0,1,116, + %%97,0, %Integer: 0. + 104,0, %Tuple {} instead of integer. + 98,6,64,82,230,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,0,0,0,48,0,0,0,0,0,97,42,97,7,106>>)), + + ?line {'EXIT',_} = + (catch + binary_to_term( + %% A new-type fun in a list containing a bad unique value. + <<131, + 108,0,0,0,1, %List, 1 element + 112,0,0,0,70,0,224,90,4,101,48,28,110,228,153,48,239,169,232,77,108,145,0,0,0,0,0,0,0,2, + 100,0,1,116, + 97,0, %Integer: 0. + %%98,6,64,82,230, %Integer. + 100,0,2,64,65, %Atom instead of integer. + 103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116,0,0,0,48,0,0,0,0,0,97,42,97,7,106>>)), + + %% An absurdly large atom. + ?line {'EXIT',_} = + (catch binary_to_term(iolist_to_binary([<<131,100,65000:16>>| + lists:duplicate(65000, 42)]))), + + %% Longer than 255 characters. + ?line {'EXIT',_} = + (catch binary_to_term(iolist_to_binary([<<131,100,256:16>>| + lists:duplicate(256, 42)]))), + + %% OTP-7218. Thanks to Matthew Dempsky. Also make sure that we + %% cover the other error cases for external funs (EXPORT_EXT). + ?line {'EXIT',_} = + (catch binary_to_term( + <<131, + 113, %EXPORT_EXP + 97,13, %Integer: 13 + 97,13, %Integer: 13 + 97,13>>)), %Integer: 13 + ?line {'EXIT',_} = + (catch binary_to_term( + <<131, + 113, %EXPORT_EXP + 100,0,1,64, %Atom: '@' + 97,13, %Integer: 13 + 97,13>>)), %Integer: 13 + ?line {'EXIT',_} = + (catch binary_to_term( + <<131, + 113, %EXPORT_EXP + 100,0,1,64, %Atom: '@' + 100,0,1,64, %Atom: '@' + 106>>)), %NIL + ?line {'EXIT',_} = + (catch binary_to_term( + <<131, + 113, %EXPORT_EXP + 100,0,1,64, %Atom: '@' + 100,0,1,64, %Atom: '@' + 98,255,255,255,255>>)), %Integer: -1 + ?line {'EXIT',_} = + (catch binary_to_term( + <<131, + 113, %EXPORT_EXP + 100,0,1,64, %Atom: '@' + 100,0,1,64, %Atom: '@' + 113,97,13,97,13,97,13>>)), %fun 13:13/13 + + %% Bad funs. + ?line {'EXIT',_} = (catch binary_to_term(fake_fun(0, lists:seq(0, 256)))), + ok. + +fake_fun(Arity, Env0) -> + Uniq = erlang:md5([]), + Index = 0, + NumFree = length(Env0), + Mod = list_to_binary(?MODULE_STRING), + OldIndex = 0, + OldUniq = 16#123456, + <<131,Pid/binary>> = term_to_binary(self()), + Env1 = [term_to_binary(Term) || Term <- Env0], + Env = << <<Bin/binary>> || <<131,Bin/binary>> <- Env1 >>, + B = <<Arity,Uniq/binary,Index:32,NumFree:32, + $d,(byte_size(Mod)):16,Mod/binary, %Module. + $a,OldIndex:8, + $b,OldUniq:32, + Pid/binary,Env/binary>>, + <<131,$p,(byte_size(B)+4):32,B/binary>>. + + +%% More bad terms submitted by Matthias Lang. +otp_5933(Config) when is_list(Config) -> + ?line try_bad_lengths(<<131,$m>>), %binary + ?line try_bad_lengths(<<131,$n>>), %bignum + ?line try_bad_lengths(<<131,$o>>), %huge bignum + ok. + +try_bad_lengths(B) -> + try_bad_lengths(B, 16#FFFFFFFF). + +try_bad_lengths(B, L) when L > 16#FFFFFFF0 -> + Bin = <<B/binary,L:32>>, + io:format("~p\n", [Bin]), + {'EXIT',_} = (catch binary_to_term(Bin)), + try_bad_lengths(B, L-1); +try_bad_lengths(_, _) -> ok. + + +otp_6817(Config) when is_list(Config) -> + process_flag(min_heap_size, 20000), %Use the heap, not heap fragments. + + %% Floats are only validated when the heap fragment has been allocated. + BadFloat = <<131,99,53,46,48,$X,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,101,45,48,49,0,0,0,0,0>>, + ?line otp_6817_try_bin(BadFloat), + + %% {Binary,BadFloat}: When the error in float is discovered, a refc-binary + %% has been allocated and the list of refc-binaries goes through the + %% limbo area between the heap top and stack. + BinAndFloat = + <<131,104,2,109,0,0,1,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20, + 21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45, + 46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70, + 71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, + 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115, + 116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134, + 135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153, + 154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172, + 173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229, + 230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248, + 249,250,251,252,253,254,255,99,51,46,49,52,$B,$l,$u,$r,$f,48,48,48,48,48,48, + 48,48,49,50,52,51,52,101,43,48,48,0,0,0,0,0>>, + ?line otp_6817_try_bin(BinAndFloat), + + %% {Fun,BadFloat} + FunAndFloat = + <<131,104,2,112,0,0,0,66,0,238,239,135,138,137,216,89,57,22,111,52,126,16,84, + 71,8,0,0,0,0,0,0,0,0,100,0,1,116,97,0,98,5,175,169,123,103,100,0,13,110,111, + 110,111,100,101,64,110,111,104,111,115,116,0,0,0,41,0,0,0,0,0,99,50,46,55,48, + $Y,57,57,57,57,57,57,57,57,57,57,57,57,57,54,52,52,55,101,43,48,48,0,0,0,0,0>>, + ?line otp_6817_try_bin(FunAndFloat), + + %% [ExternalPid|BadFloat] + ExtPidAndFloat = + <<131,108,0,0,0,1,103,100,0,13,107,97,108,108,101,64,115,116,114,105,100,101, + 114,0,0,0,36,0,0,0,0,2,99,48,46,$@,48,48,48,48,48,48,48,48,48,48,48,48,48,48, + 48,48,48,48,48,101,43,48,48,0,0,0,0,0>>, + ?line otp_6817_try_bin(ExtPidAndFloat), + ok. + +otp_6817_try_bin(Bin) -> + erlang:garbage_collect(), + + %% If the bug is present, the heap pointer will moved when the invalid term + %% is found and we will have a linked list passing through the limbo area + %% between the heap top and the stack pointer. + catch binary_to_term(Bin), + + %% If the bug is present, we will overwrite the pointers in the limbo area. + Filler = erlang:make_tuple(1024, 16#3FA), + id(Filler), + + %% Will crash if the bug is present. + erlang:garbage_collect(). + +otp_8117(doc) -> "Some bugs in binary_to_term when 32-bit integers are negative."; +otp_8117(suite) -> []; +otp_8117(Config) when is_list(Config) -> + [otp_8117_do(Op,-(1 bsl N)) || Op <- ['fun',list,tuple], + N <- lists:seq(0,31)], + ok. + +otp_8117_do('fun',Neg) -> + % Fun with negative num_free + FunBin = term_to_binary(fun() -> ok end), + ?line <<B1:27/binary,_NumFree:32,Rest/binary>> = FunBin, + ?line bad_bin_to_term(<<B1/binary,Neg:32,Rest/binary>>); +otp_8117_do(list,Neg) -> + %% List with negative length + ?line bad_bin_to_term(<<131,104,2,108,Neg:32,97,11,104,1,97,12,97,13,106,97,14>>); +otp_8117_do(tuple,Neg) -> + %% Tuple with negative arity + ?line bad_bin_to_term(<<131,104,2,105,Neg:32,97,11,97,12,97,13,97,14>>). + + +ordering(doc) -> "Tests ordering of binaries."; +ordering(suite) -> []; +ordering(Config) when is_list(Config) -> + B1 = list_to_binary([7,8,9]), + B2 = make_sub_binary([1,2,3,4]), + B3 = list_to_binary([1,2,3,5]), + Unaligned = make_unaligned_sub_binary(B2), + + %% From R8 binaries are compared as strings. + + ?line false = B1 == B2, + ?line false = B1 =:= B2, + ?line true = B1 /= B2, + ?line true = B1 =/= B2, + + ?line true = B1 > B2, + ?line true = B2 < B3, + ?line true = B2 =< B1, + ?line true = B2 =< B3, + + ?line true = B2 =:= Unaligned, + ?line true = B2 == Unaligned, + ?line true = Unaligned < B3, + ?line true = Unaligned =< B3, + + %% Binaries are greater than all other terms. + + ?line true = B1 > 0, + ?line true = B1 > 39827491247298471289473333333333333333333333333333, + ?line true = B1 > -3489274937438742190467869234328742398347, + ?line true = B1 > 3.14, + ?line true = B1 > [], + ?line true = B1 > [a], + ?line true = B1 > {a}, + ?line true = B1 > self(), + ?line true = B1 > make_ref(), + ?line true = B1 > xxx, + ?line true = B1 > fun() -> 1 end, + ?line true = B1 > fun erlang:send/2, + + ?line Path = ?config(priv_dir, Config), + ?line AFile = filename:join(Path, "vanilla_file"), + ?line Port = open_port(AFile, [out]), + ?line true = B1 > Port, + + ?line true = B1 >= 0, + ?line true = B1 >= 39827491247298471289473333333333333333333333333333, + ?line true = B1 >= -3489274937438742190467869234328742398347, + ?line true = B1 >= 3.14, + ?line true = B1 >= [], + ?line true = B1 >= [a], + ?line true = B1 >= {a}, + ?line true = B1 >= self(), + ?line true = B1 >= make_ref(), + ?line true = B1 >= xxx, + ?line true = B1 >= fun() -> 1 end, + ?line true = B1 >= fun erlang:send/2, + ?line true = B1 >= Port, + + ok. + +%% Test that comparisions between binaries with different alignment work. +unaligned_order(Config) when is_list(Config) -> + L = lists:seq(0, 7), + [test_unaligned_order(I, J) || I <- L, J <- L], + ok. + +test_unaligned_order(I, J) -> + Align = {I,J}, + io:format("~p ~p", [I,J]), + ?line true = test_unaligned_order_1('=:=', <<1,2,3,16#AA,16#7C,4,16#5F,5,16#5A>>, + <<1,2,3,16#AA,16#7C,4,16#5F,5,16#5A>>, + Align), + ?line false = test_unaligned_order_1('=/=', <<1,2,3>>, <<1,2,3>>, Align), + ?line true = test_unaligned_order_1('==', <<4,5,6>>, <<4,5,6>>, Align), + ?line false = test_unaligned_order_1('/=', <<1,2,3>>, <<1,2,3>>, Align), + + ?line true = test_unaligned_order_1('<', <<1,2>>, <<1,2,3>>, Align), + ?line true = test_unaligned_order_1('=<', <<1,2>>, <<1,2,3>>, Align), + ?line true = test_unaligned_order_1('=<', <<1,2,7,8>>, <<1,2,7,8>>, Align), + ok. + +test_unaligned_order_1(Op, A, B, {Aa,Ba}) -> + erlang:Op(unaligned_sub_bin(A, Aa), unaligned_sub_bin(B, Ba)). + +test_terms(Test_Func) -> + ?line Test_Func(atom), + ?line Test_Func(''), + ?line Test_Func('a'), + ?line Test_Func('ab'), + ?line Test_Func('abc'), + ?line Test_Func('abcd'), + ?line Test_Func('abcde'), + ?line Test_Func('abcdef'), + ?line Test_Func('abcdefg'), + ?line Test_Func('abcdefgh'), + + ?line Test_Func(fun() -> ok end), + X = id([a,{b,c},c]), + Y = id({x,y,z}), + Z = id(1 bsl 8*257), + ?line Test_Func(fun() -> X end), + ?line Test_Func(fun() -> {X,Y} end), + ?line Test_Func([fun() -> {X,Y,Z} end, + fun() -> {Z,X,Y} end, + fun() -> {Y,Z,X} end]), + + ?line Test_Func({trace_ts,{even_bigger,{some_data,fun() -> ok end}},{1,2,3}}), + ?line Test_Func({trace_ts,{even_bigger,{some_data,<<1,2,3,4,5,6,7,8,9,10>>}}, + {1,2,3}}), + + ?line Test_Func(1), + ?line Test_Func(42), + ?line Test_Func(-23), + ?line Test_Func(256), + ?line Test_Func(25555), + ?line Test_Func(-3333), + + ?line Test_Func(1.0), + + ?line Test_Func(183749783987483978498378478393874), + ?line Test_Func(-37894183749783987483978498378478393874), + Very_Big = very_big_num(), + ?line Test_Func(Very_Big), + ?line Test_Func(-Very_Big+1), + + ?line Test_Func([]), + ?line Test_Func("abcdef"), + ?line Test_Func([a, b, 1, 2]), + ?line Test_Func([a|b]), + + ?line Test_Func({}), + ?line Test_Func({1}), + ?line Test_Func({a, b}), + ?line Test_Func({a, b, c}), + ?line Test_Func(list_to_tuple(lists:seq(0, 255))), + ?line Test_Func(list_to_tuple(lists:seq(0, 256))), + + ?line Test_Func(make_ref()), + ?line Test_Func([make_ref(), make_ref()]), + + ?line Test_Func(make_port()), + + ?line Test_Func(make_pid()), + + ?line Test_Func(Bin0 = list_to_binary(lists:seq(0, 14))), + ?line Test_Func(Bin1 = list_to_binary(lists:seq(0, ?heap_binary_size))), + ?line Test_Func(Bin2 = list_to_binary(lists:seq(0, ?heap_binary_size+1))), + ?line Test_Func(Bin3 = list_to_binary(lists:seq(0, 255))), + + ?line Test_Func(make_unaligned_sub_binary(Bin0)), + ?line Test_Func(make_unaligned_sub_binary(Bin1)), + ?line Test_Func(make_unaligned_sub_binary(Bin2)), + ?line Test_Func(make_unaligned_sub_binary(Bin3)), + + ?line Test_Func(make_sub_binary(lists:seq(42, 43))), + ?line Test_Func(make_sub_binary([42,43,44])), + ?line Test_Func(make_sub_binary([42,43,44,45])), + ?line Test_Func(make_sub_binary([42,43,44,45,46])), + ?line Test_Func(make_sub_binary([42,43,44,45,46,47])), + ?line Test_Func(make_sub_binary([42,43,44,45,46,47,48])), + ?line Test_Func(make_sub_binary(lists:seq(42, 49))), + ?line Test_Func(make_sub_binary(lists:seq(0, 14))), + ?line Test_Func(make_sub_binary(lists:seq(0, ?heap_binary_size))), + ?line Test_Func(make_sub_binary(lists:seq(0, ?heap_binary_size+1))), + ?line Test_Func(make_sub_binary(lists:seq(0, 255))), + + ?line Test_Func(make_unaligned_sub_binary(lists:seq(42, 43))), + ?line Test_Func(make_unaligned_sub_binary([42,43,44])), + ?line Test_Func(make_unaligned_sub_binary([42,43,44,45])), + ?line Test_Func(make_unaligned_sub_binary([42,43,44,45,46])), + ?line Test_Func(make_unaligned_sub_binary([42,43,44,45,46,47])), + ?line Test_Func(make_unaligned_sub_binary([42,43,44,45,46,47,48])), + ?line Test_Func(make_unaligned_sub_binary(lists:seq(42, 49))), + ?line Test_Func(make_unaligned_sub_binary(lists:seq(0, 14))), + ?line Test_Func(make_unaligned_sub_binary(lists:seq(0, ?heap_binary_size))), + ?line Test_Func(make_unaligned_sub_binary(lists:seq(0, ?heap_binary_size+1))), + ?line Test_Func(make_unaligned_sub_binary(lists:seq(0, 255))), + + %% Bit level binaries. + ?line Test_Func(<<1:1>>), + ?line Test_Func(<<2:2>>), + ?line Test_Func(<<42:10>>), + ?line Test_Func(list_to_bitstring([<<5:6>>|lists:seq(0, 255)])), + + ?line Test_Func(F = fun(A) -> 42*A end), + ?line Test_Func(lists:duplicate(32, F)), + + ?line Test_Func(FF = fun binary_SUITE:all/1), + ?line Test_Func(lists:duplicate(32, FF)), + + ok. + +test_floats(Test_Func) -> + ?line Test_Func(5.5), + ?line Test_Func(-15.32), + ?line Test_Func(1.2435e25), + ?line Test_Func(1.2333e-20), + ?line Test_Func(199.0e+15), + ok. + +very_big_num() -> + very_big_num(33, 1). + +very_big_num(Left, Result) when Left > 0 -> + ?line very_big_num(Left-1, Result*256); +very_big_num(0, Result) -> + ?line Result. + +make_port() -> + ?line open_port({spawn, efile}, [eof]). + +make_pid() -> + ?line spawn_link(?MODULE, sleeper, []). + +sleeper() -> + ?line receive after infinity -> ok end. + + +gc_test(doc) -> "Test that binaries are garbage collected properly."; +gc_test(suite) -> []; +gc_test(Config) when is_list(Config) -> + case erlang:system_info(heap_type) of + private -> gc_test_1(); + hybrid -> {skip,"Hybrid heap"} + end. + +gc_test_1() -> + %% Note: This test is only relevant for REFC binaries. + %% Therefore, we take care that all binaries are REFC binaries. + B = list_to_binary(lists:seq(0, ?heap_binary_size)), + Self = self(), + F1 = fun() -> + gc(), + {binary,[]} = process_info(self(), binary), + Self ! {self(),done} + end, + F = fun() -> + receive go -> ok end, + {binary,[{_,65,1}]} = process_info(self(), binary), + gc(), + {B1,B2} = my_split_binary(B, 4), + gc(), + gc(), + {binary,L1} = process_info(self(), binary), + [Binfo1,Binfo2,Binfo3] = L1, + {_,65,3} = Binfo1 = Binfo2 = Binfo3, + 65 = size(B), + 4 = size(B1), + 61 = size(B2), + F1() + end, + gc(), + gc(), + 65 = size(B), + gc_test1(spawn_opt(erlang, apply, [F,[]], [link,{fullsweep_after,0}])). + +gc_test1(Pid) -> + gc(), + Pid ! go, + receive + {Pid,done} -> ok + after 10000 -> + ?line ?t:fail() + end. + +%% Like split binary, but returns REFC binaries. Only useful for gc_test/1. + +my_split_binary(B, Pos) -> + Self = self(), + Ref = make_ref(), + spawn(fun() -> Self ! {Ref,split_binary(B, Pos)} end), + receive + {Ref,Result} -> Result + end. + +gc() -> + erlang:garbage_collect(), + gc1(). +gc1() -> ok. + +bit_sized_binary_sizes(Config) when is_list(Config) -> + ?line [bsbs_1(A) || A <- lists:seq(0, 7)], + ok. + +bsbs_1(0) -> + BinSize = 32+8, + io:format("A: ~p BinSize: ~p", [0,BinSize]), + Bin = binary_to_term(<<131,$M,5:32,0,0,0,0,0,0>>), + BinSize = bit_size(Bin); +bsbs_1(A) -> + BinSize = 32+A, + io:format("A: ~p BinSize: ~p", [A,BinSize]), + Bin = binary_to_term(<<131,$M,5:32,A,0,0,0,0,0>>), + BinSize = bit_size(Bin). + +bitlevel_roundtrip(Config) when is_list(Config) -> + case ?t:is_release_available("r11b") of + true -> bitlevel_roundtrip_1(); + false -> {skip,"No R11B found"} + end. + +bitlevel_roundtrip_1() -> + Name = bitlevelroundtrip, + ?line N = list_to_atom(atom_to_list(Name) ++ "@" ++ hostname()), + ?line ?t:start_node(Name, slave, [{erl,[{release,"r11b"}]}]), + + ?line {<<128>>,1} = roundtrip(N, <<1:1>>), + ?line {<<64>>,2} = roundtrip(N, <<1:2>>), + ?line {<<16#E0>>,3} = roundtrip(N, <<7:3>>), + ?line {<<16#70>>,4} = roundtrip(N, <<7:4>>), + ?line {<<16#10>>,5} = roundtrip(N, <<2:5>>), + ?line {<<16#8>>,6} = roundtrip(N, <<2:6>>), + ?line {<<16#2>>,7} = roundtrip(N, <<1:7>>), + ?line {<<8,128>>,1} = roundtrip(N, <<8,1:1>>), + ?line {<<42,248>>,5} = roundtrip(N, <<42,31:5>>), + + ?line ?t:stop_node(N), + ok. + +roundtrip(Node, Term) -> + {badrpc,{'EXIT',Res}} = rpc:call(Node, erlang, exit, [Term]), + io:format("<<~p bits>> => ~w", [bit_size(Term),Res]), + Res. + +deep(Config) when is_list(Config) -> + ?line deep_roundtrip(lists:foldl(fun(E, A) -> + [E,A] + end, [], lists:seq(1, 1000000))), + ?line deep_roundtrip(lists:foldl(fun(E, A) -> + {E,A} + end, [], lists:seq(1, 1000000))), + ?line deep_roundtrip(lists:foldl(fun(E, A) -> + fun() -> {E,A} end + end, [], lists:seq(1, 1000000))), + ok. + +deep_roundtrip(T) -> + B = term_to_binary(T), + true = deep_eq(T, binary_to_term(B)). + +%% +%% FIXME: =:= runs out of stack. +%% +deep_eq([H1|T1], [H2|T2]) -> + deep_eq(H1, H2) andalso deep_eq(T1, T2); +deep_eq(T1, T2) when tuple_size(T1) =:= tuple_size(T2) -> + deep_eq_tup(T1, T2, tuple_size(T1)); +deep_eq(T1, T2) when is_function(T1), is_function(T2) -> + {uniq,U1} = erlang:fun_info(T1, uniq), + {index,I1} = erlang:fun_info(T1, index), + {arity,A1} = erlang:fun_info(T1, arity), + {env,E1} = erlang:fun_info(T1, env), + {uniq,U2} = erlang:fun_info(T2, uniq), + {index,I2} = erlang:fun_info(T2, index), + {arity,A2} = erlang:fun_info(T2, arity), + {env,E2} = erlang:fun_info(T2, env), + U1 =:= U2 andalso I1 =:= I2 andalso A1 =:= A2 andalso + deep_eq(E1, E2); +deep_eq(T1, T2) -> + T1 =:= T2. + +deep_eq_tup(_T1, _T2, 0) -> + true; +deep_eq_tup(T1, T2, N) -> + deep_eq(element(N, T1), element(N, T2)) andalso + deep_eq_tup(T1, T2, N-1). + +obsolete_funs(Config) when is_list(Config) -> + erts_debug:set_internal_state(available_internal_state, true), + + X = id({1,2,3}), + Y = id([a,b,c,d]), + Z = id({x,y,z}), + ?line obsolete_fun(fun() -> ok end), + ?line obsolete_fun(fun() -> X end), + ?line obsolete_fun(fun(A) -> {A,X} end), + ?line obsolete_fun(fun() -> {X,Y} end), + ?line obsolete_fun(fun() -> {X,Y,Z} end), + + ?line obsolete_fun(fun ?MODULE:all/1), + + erts_debug:set_internal_state(available_internal_state, false), + ok. + +obsolete_fun(Fun) -> + Tuple = case erlang:fun_info(Fun, type) of + {type,external} -> + {module,M} = erlang:fun_info(Fun, module), + {name,F} = erlang:fun_info(Fun, name), + {M,F}; + {type,local} -> + {module,M} = erlang:fun_info(Fun, module), + {index,I} = erlang:fun_info(Fun, index), + {uniq,U} = erlang:fun_info(Fun, uniq), + {env,E} = erlang:fun_info(Fun, env), + {'fun',M,I,U,list_to_tuple(E)} + end, + Tuple = no_fun_roundtrip(Fun). + +no_fun_roundtrip(Term) -> + binary_to_term(erts_debug:get_internal_state({term_to_binary_no_funs,Term})). + +%% Test non-standard encodings never generated by term_to_binary/1 +%% but recognized by binary_to_term/1. + +robustness(Config) when is_list(Config) -> + ?line [] = binary_to_term(<<131,107,0,0>>), %Empty string. + ?line [] = binary_to_term(<<131,108,0,0,0,0,106>>), %Zero-length list. + + %% {[],a} where [] is a zero-length list. + ?line {[],a} = binary_to_term(<<131,104,2,108,0,0,0,0,106,100,0,1,97>>), + + %% {42,a} where 42 is a zero-length list with 42 in the tail. + ?line {42,a} = binary_to_term(<<131,104,2,108,0,0,0,0,97,42,100,0,1,97>>), + + %% {{x,y},a} where {x,y} is a zero-length list with {x,y} in the tail. + ?line {{x,y},a} = binary_to_term(<<131,104,2,108,0,0,0,0, + 104,2,100,0,1,120,100,0,1, + 121,100,0,1,97>>), + + %% Bignums fitting in 32 bits. + ?line 16#7FFFFFFF = binary_to_term(<<131,98,127,255,255,255>>), + ?line -1 = binary_to_term(<<131,98,255,255,255,255>>), + + ok. + +%% OTP-8180: Test several terms that have been known to crash the emulator. +%% (Thanks to Scott Lystig Fritchie.) +otp_8180(Config) when is_list(Config) -> + ?line Data = ?config(data_dir, Config), + ?line Wc = filename:join(Data, "zzz.*"), + Files = filelib:wildcard(Wc), + [run_otp_8180(F) || F <- Files], + ok. + +run_otp_8180(Name) -> + io:format("~s", [Name]), + ?line {ok,Bins} = file:consult(Name), + [begin + io:format("~p\n", [Bin]), + ?line {'EXIT',{badarg,_}} = (catch binary_to_term(Bin)) + end || Bin <- Bins], + ok. + +%% Utilities. + +make_sub_binary(Bin) when is_binary(Bin) -> + {_,B} = split_binary(list_to_binary([0,1,3,Bin]), 3), + B; +make_sub_binary(List) -> + make_sub_binary(list_to_binary(List)). + +make_unaligned_sub_binary(Bin0) when is_binary(Bin0) -> + Bin1 = <<0:3,Bin0/binary,31:5>>, + Sz = size(Bin0), + <<0:3,Bin:Sz/binary,31:5>> = id(Bin1), + Bin; +make_unaligned_sub_binary(List) -> + make_unaligned_sub_binary(list_to_binary(List)). + +%% Add 1 bit to the size of the binary. +bit_sized_binary(Bin0) -> + Bin = <<Bin0/binary,1:1>>, + BitSize = bit_size(Bin), + BitSize = 8*size(Bin) + 1, + Bin. + +unaligned_sub_bin(Bin, 0) -> Bin; +unaligned_sub_bin(Bin0, Offs) -> + F = random:uniform(256), + Roffs = 8-Offs, + Bin1 = <<F:Offs,Bin0/binary,F:Roffs>>, + Sz = size(Bin0), + <<_:Offs,Bin:Sz/binary,_:Roffs>> = id(Bin1), + Bin. + +hostname() -> + from($@, atom_to_list(node())). + +from(H, [H | T]) -> T; +from(H, [_ | T]) -> from(H, T); +from(_, []) -> []. + +id(I) -> I. diff --git a/erts/emulator/test/binary_SUITE_data/bad_binary b/erts/emulator/test/binary_SUITE_data/bad_binary Binary files differnew file mode 100644 index 0000000000..6c008e96ee --- /dev/null +++ b/erts/emulator/test/binary_SUITE_data/bad_binary diff --git a/erts/emulator/test/binary_SUITE_data/zzz.terms.1197 b/erts/emulator/test/binary_SUITE_data/zzz.terms.1197 new file mode 100644 index 0000000000..762e89c342 --- /dev/null +++ b/erts/emulator/test/binary_SUITE_data/zzz.terms.1197 @@ -0,0 +1 @@ +<<131,104,3,108,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,16,52,164,138,66,218,149,102,245,119,235,94,64,69,150,116,121,109,0,0,0,16,69,128,138,148,31,134,101,69,254,137,55,67,50,87,61,209,109,0,0,0,16,102,135,75,119,127,212,19,209,35,70,255,181,98,150,204,245,109,0,0,0,16,249,179,20,179,193,238,148,70,246,210,217,238,180,230,213,19,109,0,0,0,16,53,94,111,136,10,236,80,242,175,115,246,172,67,209,60,111,109,0,0,0,16,215,248,244,92,112,145,239,153,42,113,41,150,30,100,224,175,109,0,0,0,16,200,44,221,92,158,142,48,188,76,52,143,53,27,36,227,193,109,0,0,0,16,103,194,1,2,29,34,16,42,54,48,191,81,89,103,122,214,106,107,0,9,10,21,25,30,7,36,41,12,10,107,0,30,45,33,40,4,13,27,38,10,3,25,39,0,18,4,3,4,20,8,46,20,6,33,2,23,10,12,37,33,45,33>>. diff --git a/erts/emulator/test/binary_SUITE_data/zzz.terms.2224 b/erts/emulator/test/binary_SUITE_data/zzz.terms.2224 new file mode 100644 index 0000000000..6440db5f8a --- /dev/null +++ b/erts/emulator/test/binary_SUITE_data/zzz.terms.2224 @@ -0,0 +1 @@ +<<131,104,3,108,176,0,0,1,109,0,0,0,16,212,29,140,217,143,0,178,4,233,128,9,152,236,248,66,126,106,107,0,1,0,107,0,3,1,6,4>>. diff --git a/erts/emulator/test/binary_SUITE_data/zzz.terms.24619 b/erts/emulator/test/binary_SUITE_data/zzz.terms.24619 new file mode 100644 index 0000000000..e0f28775a2 --- /dev/null +++ b/erts/emulator/test/binary_SUITE_data/zzz.terms.24619 @@ -0,0 +1 @@ +<<131,104,3,108,157,157,0,7,109,0,0,0,16,55,233,12,238,67,82,29,243,29,211,100,103,94,222,253,111,109,0,0,0,16,123,199,42,7,103,210,55,190,77,163,10,206,25,26,205,194,109,0,0,0,16,112,190,42,171,14,14,14,14,14,14,14,14,14,73,114,31,109,0,0,0,16,36,164,198,221,134,71,27,5,151,55,181,122,115,75,182,107,109,0,0,0,16,191,181,181,232,197,52,185,67,212,192,200,78,208,248,48,138,109,0,0,0,16,58,191,0,250,97,191,174,47,255,145,51,55,94,20,36,22,109,0,0,0,16,19,32,200,163,20,224,40,199,252,222,64,38,59,226,140,105,106,107,0,7,6,1,4,9,5,6,4,107,0,6,8,7,9,9,0,6>>. diff --git a/erts/emulator/test/binary_SUITE_data/zzz.terms.25681 b/erts/emulator/test/binary_SUITE_data/zzz.terms.25681 new file mode 100644 index 0000000000..482d11fdf1 --- /dev/null +++ b/erts/emulator/test/binary_SUITE_data/zzz.terms.25681 @@ -0,0 +1 @@ +<<131,104,3,108,146,146,146,146,109,0,0,0,16,5,44,160,195,30,175,203,35,219,89,215,184,2,78,94,170,106,107,0,1,4,107,0,4,2,5,3,0>>. diff --git a/erts/emulator/test/binary_SUITE_data/zzz.terms.26563 b/erts/emulator/test/binary_SUITE_data/zzz.terms.26563 new file mode 100644 index 0000000000..abc33dba0a --- /dev/null +++ b/erts/emulator/test/binary_SUITE_data/zzz.terms.26563 @@ -0,0 +1 @@ +<<131,104,3,108,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,43,35,116,53,8,115,151,70,109,0,0,0,16,46,214,206,144,145,5,5,151,216,205,186,160,20,122,56,211,109,0,0,0,16,231,252,248,228,158,57,175,60,102,175,36,111,220,245,53,223,109,0,0,0,16,11,114,118,250,109,208,21,68,191,28,20,37,85,92,109,233,109,0,0,0,16,241,70,203,137,71,9,64,196,13,97,57,45,198,58,101,16,109,0,0,0,16,55,10,73,208,111,248,3,206,218,97,250,249,167,97,111,253,106,107,0,6,10,17,13,21,18,3,107,0,22,10,24,17,24,18,11,9,2,10,5,8,13,16,12,21,3,12,15,24,15,9,11>>. diff --git a/erts/emulator/test/binary_SUITE_data/zzz.terms.26744 b/erts/emulator/test/binary_SUITE_data/zzz.terms.26744 new file mode 100644 index 0000000000..5d2e0460df --- /dev/null +++ b/erts/emulator/test/binary_SUITE_data/zzz.terms.26744 @@ -0,0 +1 @@ +<<131,104,3,108,0,0,0,34,109,0,0,0,16,246,40,48,114,226,31,172,131,140,186,199,103,184,69,163,250,109,0,0,0,16,70,137,87,84,123,59,151,104,51,248,19,182,201,216,104,107,109,0,0,0,16,75,247,173,46,233,103,101,172,74,156,58,219,100,163,0,15,109,0,0,0,16,165,61,109,30,82,118,124,174,79,99,109,226,67,30,250,201,109,0,0,0,16,171,87,99,231,11,27,105,249,22,185,117,13,190,221,68,43,109,0,0,0,16,28,138,81,135,98,250,241,78,63,129,1,111,189,226,232,62,109,0,0,0,16,140,242,136,145,115,249,196,75,89,2,77,154,77,146,188,139,109,0,0,0,16,23,94,33,183,84,175,41,135,44,181,221,17,82,139,116,240,109,0,0,0,16,25,92,169,206,39,56,163,245,227,229,124,198,10,125,58,216,109,0,0,0,16,242,242,226,156,245,143,114,37,12,97,30,171,229,203,72,148,109,0,0,0,16,88,244,34,176,67,151,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,44,229,66,176,163,15,18,95,127,249,160,57,55,191,22,109,0,0,0,16,216,32,191,62,114,130,211,165,62,177,139,90,101,213,148,153,109,0,0,0,16,89,69,176,67,182,240,212,246,155,244,183,194,27,76,211,241,109,0,0,0,16,89,223,126,234,29,229,230,116,177,209,128,89,205,173,125,192,109,0,0,0,16,0,223,16,80,225,217,146,95,191,172,211,105,204,53,184,0,109,0,0,0,16,109,122,166,47,188,116,57,251,215,211,182,101,15,67,248,98,109,0,0,0,16,30,14,197,5,205,206,164,77,34,144,27,11,45,20,124,37,109,0,0,0,16,120,12,166,133,0,60,236,29,97,123,234,166,243,70,225,190,109,0,0,0,16,153,158,57,172,15,245,115,49,233,53,112,251,201,28,250,95,109,0,0,0,16,253,120,180,234,85,203,127,112,237,225,193,159,73,44,64,231,109,0,0,0,16,18,51,70,243,111,230,11,148,243,73,182,43,168,82,227,129,109,0,0,0,16,61,147,55,3,76,53,153,52,117,47,51,176,153,85,97,216,109,0,0,0,16,113,142,196,76,220,119,212,32,42,51,80,42,159,137,71,183,109,0,0,0,16,207,4,245,17,147,229,41,4,66,99,23,243,85,156,222,34,109,0,0,0,16,146,201,209,199,145,105,193,201,188,11,226,207,215,23,156,30,109,0,0,0,16,141,156,48,124,183,243,196,163,40,34,165,25,34,209,206,170,109,0,0,0,16,160,252,133,213,54,168,44,75,148,247,79,183,170,194,80,228,109,0,0,0,16,221,101,172,89,69,146,157,172,253,251,151,231,116,217,76,209,109,0,0,0,16,250,199,222,195,91,93,106,169,252,80,246,217,80,160,207,76,109,0,0,0,16,146,101,163,61,212,184,154,55,158,19,200,188,141,102,164,115,109,0,0,0,16,80,97,213,9,68,43,15,183,17,103,106,252,92,177,75,49,109,0,0,0,16,14,108,183,17,228,213,68,27,3,156,218,105,141,132,206,120,109,0,0,0,16,85,46,106,151,41,124,83,229,146,32,140,249,127,187,59,96,106,107,0,34,4,7,13,36,26,38,29,4,2,9,10,38,20,41,10,38,44,44,27,38,9,20,41,19,3,41,1,19,22,14,6,37,16,9,107,0,21,29,44,0,11,30,4,5,12,45,44,11,43,11,21,42,27,45,16,44,11,46>>. diff --git a/erts/emulator/test/binary_SUITE_data/zzz.terms.27459 b/erts/emulator/test/binary_SUITE_data/zzz.terms.27459 new file mode 100644 index 0000000000..8ce2f4f676 --- /dev/null +++ b/erts/emulator/test/binary_SUITE_data/zzz.terms.27459 @@ -0,0 +1 @@ +<<131,104,3,108,0,0,0,22,109,0,0,0,16,226,66,101,167,212,253,41,123,50,225,132,86,201,118,10,221,109,0,0,0,16,169,167,250,110,49,5,132,236,14,41,12,236,33,224,162,32,109,0,0,0,16,19,212,176,127,21,145,23,227,37,69,236,192,15,15,88,151,109,0,0,0,16,59,91,152,82,86,126,247,97,138,172,127,95,45,116,239,116,109,0,0,0,16,20,167,126,55,177,97,157,117,16,231,14,242,108,48,99,108,109,0,0,0,16,164,40,48,217,95,155,48,112,128,190,231,207,101,255,133,46,109,0,0,0,16,106,176,58,142,146,193,78,37,119,98,59,15,159,223,27,213,109,0,0,0,16,11,124,59,66,82,164,203,178,45,254,62,41,149,60,186,80,109,0,0,0,16,109,178,163,249,96,68,62,121,3,244,194,251,10,56,39,200,109,0,0,0,16,212,29,140,217,143,0,178,4,233,128,9,152,236,248,66,126,109,0,0,0,16,156,22,40,137,15,93,180,84,160,180,174,215,114,13,224,148,109,0,0,0,16,93,94,191,98,203,74,126,252,62,90,216,238,14,13,138,247,109,0,0,0,16,136,233,85,1,4,240,228,125,156,73,95,136,32,15,55,89,109,0,0,0,16,142,34,55,192,14,202,6,201,109,29,102,197,165,181,70,199,109,0,0,0,16,195,209,131,241,209,212,72,96,92,244,0,245,215,133,84,79,109,0,0,0,16,125,74,14,90,3,167,45,63,216,3,89,225,61,100,248,35,109,0,0,0,16,39,87,149,29,170,91,68,106,115,163,48,196,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,252,10,34,41,217,19,207,125,36,59,89,207,34,55,138,91,109,0,0,0,16,32,110,118,6,239,38,57,44,131,209,5,122,105,63,68,184,109,0,0,0,16,27,187,87,135,62,179,16,242,240,163,46,113,111,99,144,218,109,0,0,0,16,17,40,32,235,194,249,160,229,181,252,153,106,65,252,184,124,106,107,0,22,5,23,26,4,13,21,19,25,27,0,2,10,18,2,29,11,12,5,25,8,3,17,107,0,19,21,20,0,2,18,22,1,33,3,32,20,2,19,14,19,16,19,28,33>>. diff --git a/erts/emulator/test/binary_SUITE_data/zzz.terms.527 b/erts/emulator/test/binary_SUITE_data/zzz.terms.527 new file mode 100644 index 0000000000..d70c79b868 --- /dev/null +++ b/erts/emulator/test/binary_SUITE_data/zzz.terms.527 @@ -0,0 +1 @@ +<<131,104,3,108,183,183,183,183,183,183,183,183,183,212,29,140,217,143,0,178,4,233,128,9,152,236,248,66,126,109,0,0,0,16,111,126,36,22,107,79,30,119,213,219,164,180,225,120,123,224,109,0,0,0,16,14,69,79,49,229,113,56,180,7,19,44,94,76,79,28,42,109,0,0,0,16,251,14,34,199,154,199,86,121,233,136,30,107,161,131,179,84,109,0,0,0,16,230,230,11,16,202,117,16,238,148,246,255,105,98,84,219,245,109,0,0,0,16,212,29,140,217,143,0,178,4,233,128,9,152,236,248,66,126,109,0,0,0,16,223,31,62,219,145,21,172,176,161,224,66,9,183,169,147,123,109,0,0,0,16,243,121,234,243,200,49,176,77,225,83,70,157,27,236,52,94,109,0,0,0,16,102,186,19,229,71,77,36,30,128,247,161,46,212,52,100,93,109,0,0,0,16,226,185,112,99,61,36,116,197,254,193,204,138,97,228,254,178,109,0,0,0,16,230,253,160,240,211,224,173,255,246,158,51,68,98,209,239,106,109,0,0,0,16,212,29,140,217,143,0,178,4,233,128,9,152,236,248,66,126,109,0,0,0,16,109,53,240,214,48,20,94,143,112,27,180,172,186,100,207,103,109,0,0,0,16,185,122,218,11,245,247,117,236,175,192,101,22,47,247,213,93,109,0,0,0,16,55,83,136,179,218,183,199,99,80,205,69,122,209,147,136,162,109,0,0,0,16,127,11,36,195,150,130,218,123,120,49,162,50,95,182,15,195,106,107,0,16,0,2,3,5,11,0,2,6,10,14,2,0,12,17,3,5,107,0,3,3,10,2>>. diff --git a/erts/emulator/test/binary_SUITE_data/zzz.terms.8929 b/erts/emulator/test/binary_SUITE_data/zzz.terms.8929 new file mode 100644 index 0000000000..9a31f48823 --- /dev/null +++ b/erts/emulator/test/binary_SUITE_data/zzz.terms.8929 @@ -0,0 +1 @@ +<<131,104,3,108,0,0,0,21,109,0,0,0,16,123,228,24,65,132,178,1,218,6,16,174,5,79,241,119,229,109,0,0,0,16,183,232,168,242,114,241,182,252,130,145,187,84,195,110,40,25,109,0,0,0,16,66,82,177,244,114,57,249,15,18,65,96,242,176,74,53,28,109,0,0,0,16,47,133,166,135,215,134,84,208,17,228,162,235,112,124,148,175,109,0,0,0,16,63,40,157,117,204,109,93,163,234,121,88,204,132,5,20,13,109,0,0,0,16,61,43,105,42,38,153,95,240,96,250,203,163,119,26,60,213,109,0,0,0,16,210,182,163,73,245,168,197,235,86,247,170,147,57,54,191,53,109,0,0,0,16,115,123,197,83,101,37,58,233,125,174,138,46,126,247,215,92,109,0,0,0,16,1,255,56,198,14,1,187,166,68,144,31,120,55,83,173,248,109,0,0,0,16,194,65,213,139,79,189,84,102,162,249,58,2,119,30,134,91,109,0,0,0,16,63,48,4,66,133,134,117,230,157,150,136,210,143,30,94,155,109,0,0,0,16,15,192,239,194,248,186,65,210,185,236,136,68,211,183,140,202,109,0,0,0,16,147,139,158,102,146,47,236,193,207,187,249,192,209,174,224,63,109,0,0,0,16,37,246,103,28,128,66,188,29,13,164,191,101,236,147,220,38,109,0,0,0,16,192,5,210,30,111,116,229,81,90,183,152,255,37,27,203,136,109,0,0,0,16,79,158,149,156,199,24,38,151,226,113,87,159,1,52,165,103,109,0,0,0,16,56,202,139,53,165,157,149,169,169,253,235,156,199,62,23,124,109,0,0,0,16,53,97,55,75,222,77,234,235,193,28,105,92,95,73,124,38,109,0,0,0,16,37,248,57,253,174,178,47,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,0,0,0,16,105,105,28,123,220,195,206,109,93,138,19,97,242,45,4,172,106,107,0,21,29,26,34,20,23,42,44,21,6,8,33,25,29,41,16,15,34,27,9,30,1,107,0,10,42,24,26,42,13,35,23,18,12,3>>. diff --git a/erts/emulator/test/bs_bincomp_SUITE.erl b/erts/emulator/test/bs_bincomp_SUITE.erl new file mode 100644 index 0000000000..4e83d97689 --- /dev/null +++ b/erts/emulator/test/bs_bincomp_SUITE.erl @@ -0,0 +1,130 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% Originally based on Per Gustafsson's test suite. +%% + +-module(bs_bincomp_SUITE). + +-export([all/1, + byte_aligned/1,bit_aligned/1,extended_byte_aligned/1, + extended_bit_aligned/1,mixed/1,tracing/1]). + +-include("test_server.hrl"). + +all(suite) -> + [byte_aligned,bit_aligned,extended_byte_aligned, + extended_bit_aligned,mixed,tracing]. + + +byte_aligned(Config) when is_list(Config) -> + <<"abcdefg">> = << <<(X+32)>> || <<X>> <= <<"ABCDEFG">> >>, + <<1:32/little,2:32/little,3:32/little,4:32/little>> = + << <<X:32/little>> || <<X:32>> <= <<1:32,2:32,3:32,4:32>> >>, + <<1:32/little,2:32/little,3:32/little,4:32/little>> = + << <<X:32/little>> || <<X:16>> <= <<1:16,2:16,3:16,4:16>> >>, + ok. + +bit_aligned(Config) when is_list(Config) -> + <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> = + << <<(X+32):7>> || <<X>> <= <<"ABCDEFG">> >>, + <<"ABCDEFG">> = + << <<(X-32)>> || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> >>, + <<1:31/little,2:31/little,3:31/little,4:31/little>> = + << <<X:31/little>> || <<X:31>> <= <<1:31,2:31,3:31,4:31>> >>, + <<1:31/little,2:31/little,3:31/little,4:31/little>> = + << <<X:31/little>> || <<X:15>> <= <<1:15,2:15,3:15,4:15>> >>, + ok. + +extended_byte_aligned(Config) when is_list(Config) -> + <<"abcdefg">> = << <<(X+32)>> || X <- "ABCDEFG" >>, + "abcdefg" = [(X+32) || <<X>> <= <<"ABCDEFG">>], + <<1:32/little,2:32/little,3:32/little,4:32/little>> = + << <<X:32/little>> || X <- [1,2,3,4] >>, + [256,512,768,1024] = + [X || <<X:16/little>> <= <<1:16,2:16,3:16,4:16>>], + ok. + +extended_bit_aligned(Config) when is_list(Config) -> + <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> = + << <<(X+32):7>> || X <- "ABCDEFG" >>, + "ABCDEFG" = [(X-32) || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>], + <<1:31/little,2:31/little,3:31/little,4:31/little>> = + << <<X:31/little>> || X <- [1,2,3,4] >>, + [256,512,768,1024] = + [X || <<X:15/little>> <= <<1:15,2:15,3:15,4:15>>], + ok. + +mixed(Config) when is_list(Config) -> + <<2,3,3,4,4,5,5,6>> = + << <<(X+Y)>> || <<X>> <= <<1,2,3,4>>, <<Y>> <= <<1,2>> >>, + <<2,3,3,4,4,5,5,6>> = + << <<(X+Y)>> || <<X>> <= <<1,2,3,4>>, Y <- [1,2] >>, + <<2,3,3,4,4,5,5,6>> = + << <<(X+Y)>> || X <- [1,2,3,4], Y <- [1,2] >>, + [2,3,3,4,4,5,5,6] = + [(X+Y) || <<X>> <= <<1,2,3,4>>, <<Y>> <= <<1,2>>], + [2,3,3,4,4,5,5,6] = + [(X+Y) || <<X>> <= <<1,2,3,4>>, Y <- [1,2]], + <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = + << <<(X+Y):3>> || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, <<Y:3>> <= <<1:3,2:3>> >>, + <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = + << <<(X+Y):3>> || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, Y <- [1,2] >>, + <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = + << <<(X+Y):3>> || X <- [1,2,3,4], Y <- [1,2] >>, + [2,3,3,4,4,5,5,6] = + [(X+Y) || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, <<Y:3>> <= <<1:3,2:3>>], + [2,3,3,4,4,5,5,6] = + [(X+Y) || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, Y <- [1,2]], + ok. + +%% OTP-8179: Call tracing on binary comprehensions would cause a crash. +tracing(Config) when is_list(Config) -> + Self = self(), + Tracer = spawn_opt(fun() -> tracer(Self, 0) end, + [link,{priority,max}]), + Pattern = [{'_',[],[{return_trace}]}], + erlang:trace_pattern({?MODULE,'_','_'}, Pattern, [local]), + erlang:trace(self(), true, [call,{tracer,Tracer}]), + random_binaries(1000), + Tracer ! done, + receive + {Tracer,N} -> + {comment,integer_to_list(N) ++ " trace messages"} + end. + +random_binary() -> + Seq = [1,2,3,4,5,6,7,8,9,10], + << <<($a + random:uniform($z - $a)):8>> || _ <- Seq >>. + +random_binaries(N) when N > 0 -> + random_binary(), + random_binaries(N - 1); +random_binaries(_) -> ok. + +tracer(Parent, N) -> + receive + Msg -> + case Msg of + done -> + Parent ! {self(),N}; + _ -> + tracer(Parent, N+1) + end + end. diff --git a/erts/emulator/test/bs_bit_binaries_SUITE.erl b/erts/emulator/test/bs_bit_binaries_SUITE.erl new file mode 100644 index 0000000000..52bb925385 --- /dev/null +++ b/erts/emulator/test/bs_bit_binaries_SUITE.erl @@ -0,0 +1,183 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% Originally based on Per Gustafsson's test suite. +%% + +-module(bs_bit_binaries_SUITE). + +-export([all/1, + misc/1,horrid_match/1,test_bitstr/1,test_bit_size/1,asymmetric_tests/1, + big_asymmetric_tests/1,binary_to_and_from_list/1, + big_binary_to_and_from_list/1,send_and_receive/1, + send_and_receive_alot/1,append/1]). + +-include("test_server.hrl"). + +all(suite) -> + [misc,horrid_match,test_bitstr,test_bit_size,asymmetric_tests, + big_asymmetric_tests,binary_to_and_from_list,big_binary_to_and_from_list, + send_and_receive,send_and_receive_alot,append]. + +misc(Config) when is_list(Config) -> + ?line <<1:100>> = id(<<1:100>>), + ?line {ok,ok} = {match(7),match(9)}, + ?line {ok,ok} = {match1(15),match1(31)}, + ok. + + +match(N) -> + %% Move N to a Y register to cover another instruction. + <<0:N>> = id(<<0:N>>), + <<0:N,0:1>> = id(<<0:N,0:1>>), + ok. + +match1(N) -> + %% Putting the binary inside a list will force another + %% instruction to be used. + [<<42:N/little>>] = id([<<42:N/little>>]), + ok. + +test_bit_size(Config) when is_list(Config) -> + ?line 101 = bit_size(<<1:101>>), + ?line 1001 = bit_size(<<1:1001>>), + ?line 80 = bit_size(<<1:80>>), + ?line 800 = bit_size(<<1:800>>), + ?line Bin = <<0:16#1000000>>, + ?line BigBin = list_to_bitstring([Bin||_ <- lists:seq(1,16#10)]++[<<1:1>>]), + ?line 16#10000001 = erlang:bit_size(BigBin), + %% Only run these on computers with lots of memory + %% HugeBin = list_to_bitstring([BigBin||_ <- lists:seq(1,16#10)]++[<<1:1>>]), + %% 16#100000011 = bit_size(HugeBin), + ?line 0 = bit_size(<<>>), + ok. + +horrid_match(Config) when is_list(Config) -> + ?line <<1:4,B:24/bitstring>> = <<1:4,42:24/little>>, + ?line <<42:24/little>> = B, + ok. + +test_bitstr(Config) when is_list(Config) -> + ?line <<1:7,B/bitstring>> = <<1:7,<<1:1,6>>/bitstring>>, + ?line <<1:1,6>> = B, + ?line B = <<1:1,6>>, + ok. + +asymmetric_tests(Config) when is_list(Config) -> + ?line <<1:12>> = <<0,1:4>>, + ?line <<0,1:4>> = <<1:12>>, + ?line <<1:1,X/bitstring>> = <<128,255,0,0:2>>, + ?line <<1,254,0,0:1>> = X, + ?line X = <<1,254,0,0:1>>, + ?line <<1:1,X1:25/bitstring>> = <<128,255,0,0:2>>, + ?line <<1,254,0,0:1>> = X1, + ?line X1 = <<1,254,0,0:1>>, + ok. + +big_asymmetric_tests(Config) when is_list(Config) -> + ?line <<1:875,1:12>> = <<1:875,0,1:4>>, + ?line <<1:875,0,1:4>> = <<1:875,1:12>>, + ?line <<1:1,X/bitstring>> = <<128,255,0,0:2,1:875>>, + ?line <<1,254,0,0:1,1:875>> = X, + ?line X = <<1,254,0,0:1,1:875>>, + ?line <<1:1,X1:900/bitstring>> = <<128,255,0,0:2,1:875>>, + ?line <<1,254,0,0:1,1:875>> = X1, + ?line X1 = <<1,254,0,0:1,1:875>>, + ok. + +binary_to_and_from_list(Config) when is_list(Config) -> + ?line <<1,2,3,4,1:1>> = list_to_bitstring(bitstring_to_list(<<1,2,3,4,1:1>>)), + ?line [1,2,3,4,<<1:1>>] = bitstring_to_list(<<1,2,3,4,1:1>>), + ?line <<1:1,1,2,3,4>> = list_to_bitstring([<<1:1>>,1,2,3,4]), + ?line [128,129,1,130,<<0:1>>] = bitstring_to_list(<<1:1,1,2,3,4>>), + ok. + +big_binary_to_and_from_list(Config) when is_list(Config) -> + ?line <<1:800,2,3,4,1:1>> = list_to_bitstring(bitstring_to_list(<<1:800,2,3,4,1:1>>)), + ?line [1,2,3,4|_Rest1] = bitstring_to_list(<<1,2,3,4,1:800,1:1>>), + ?line <<1:801,1,2,3,4>> = list_to_bitstring([<<1:801>>,1,2,3,4]), + ok. + +send_and_receive(Config) when is_list(Config) -> + ?line Bin = <<1,2:7>>, + Pid = spawn_link(fun() -> receiver(Bin) end), + ?line Pid ! {self(),<<1:7,8:5,Bin/bitstring>>}, + ?line receive + ok -> + ok + end. + +receiver(Bin) -> + receive + {Pid,<<1:7,8:5,Bin/bitstring>>} -> + Pid ! ok + end. + +send_and_receive_alot(Config) when is_list(Config) -> + Bin = <<1:1000001>>, + Pid = spawn_link(fun() -> receiver_alot(Bin) end), + spamalot(100,Bin,Pid). + +spamalot(N,Bin,Pid) when N > 0 -> + Pid ! {self(),<<1:7,8:5,Bin/bitstring>>}, + receive + ok -> + ok + end, + spamalot(N-1,Bin,Pid); +spamalot(0,_Bin,Pid) -> + Pid ! no_more, + ok. + +receiver_alot(Bin) -> + receive + {Pid,<<1:7,8:5,Bin/bitstring>>} -> + Pid ! ok; + no_more -> ok + end, + receiver_alot(Bin). + +append(Config) when is_list(Config) -> + cs_init(), + ?line <<(-1):256/signed-unit:8>> = cs(do_append(id(<<>>), 256*8)), + ?line <<(-1):256/signed-unit:8>> = cs(do_append2(id(<<>>), 256*4)), + cs_end(). + +do_append(Bin, N) when N > 0 -> do_append(<<Bin/bits,1:1>>, N-1); +do_append(Bin, 0) -> Bin. + +do_append2(Bin, N) when N > 0 -> do_append2(<<Bin/bits,3:2>>, N-1); +do_append2(Bin, 0) -> Bin. + +cs_init() -> + erts_debug:set_internal_state(available_internal_state, true), + ok. + +cs_end() -> + erts_debug:set_internal_state(available_internal_state, false), + ok. + +%% Verify that the allocated size is exact (rounded up to the nearest byte). +cs(Bin) -> + ByteSize = byte_size(Bin), + {refc_binary,ByteSize,{binary,ByteSize},_} = + erts_debug:get_internal_state({binary_info,Bin}), + Bin. + +id(I) -> I. diff --git a/erts/emulator/test/bs_construct_SUITE.erl b/erts/emulator/test/bs_construct_SUITE.erl new file mode 100644 index 0000000000..3d9b51d278 --- /dev/null +++ b/erts/emulator/test/bs_construct_SUITE.erl @@ -0,0 +1,790 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% Purpose : Common utilities used by several optimization passes. +%% + +-module(bs_construct_SUITE). + +-export([all/1, + test1/1, test2/1, test3/1, test4/1, test5/1, testf/1, + not_used/1, in_guard/1, + mem_leak/1, coerce_to_float/1, bjorn/1, + huge_float_field/1, huge_binary/1, system_limit/1, badarg/1, + copy_writable_binary/1, kostis/1, dynamic/1, bs_add/1, + otp_7422/1]). + +-include("test_server.hrl"). + +all(suite) -> + [test1, test2, test3, test4, test5, testf, + not_used, in_guard, mem_leak, coerce_to_float, bjorn, + huge_float_field, huge_binary, system_limit, badarg, + copy_writable_binary, kostis, dynamic, bs_add, + otp_7422]. + +big(1) -> + 57285702734876389752897683. + +i(X) -> X. + +r(L) -> + lists:reverse(L). + +-define(T(B, L), {B, ??B, L}). +-define(N(B), {B, ??B, unknown}). + +-define(FAIL(Expr), ?line fail_check(catch Expr, ??Expr, [])). + +-define(FAIL_VARS(Expr, Vars), ?line fail_check(catch Expr, ??Expr, Vars)). + +l(I_13, I_big1) -> + [ + ?T(<<-43>>, + [256-43]), + ?T(<<56>>, + [56]), + ?T(<<1,2>>, + [1, 2]), + ?T(<<4:4, 7:4>>, + [4*16+7]), + ?T(<<777:16/big>>, + [3, 9]), + ?T(<<777:16/little>>, + [9, 3]), + ?T(<<0.0:32/float>>, + [0,0,0,0]), + ?T(<<0.125:32/float>>, + [62,0,0,0]), + ?T(<<0.125:32/little-float>>, + [0,0,0,62]), + ?T(<<I_big1:32>>, + [138, 99, 0, 147]), + ?T(<<57285702734876389752897684:32>>, + [138, 99, 0, 148]), + ?T(<<I_big1:32/little>>, + r([138, 99, 0, 147])), + ?T(<<-1:17/unit:8>>, + lists:duplicate(17, 255)), + + ?T(<<I_13>>, + [13]), + + ?T(<<4:8/unit:2,5:2/unit:8>>, + [0, 4, 0, 5]), + + ?T(<<1:1, 0:6, 1:1>>, + [129]), + ?T(<<1:1/little, 0:6/little, 1:1/little>>, + [129]), + + ?T(<<<<1,2>>/binary>>, + [1, 2]), + ?T(<<<<1,2>>:1/binary>>, + [1]), + ?T(<<4,3,<<1,2>>:1/binary>>, + [4,3,1]), + + ?T(<<(256*45+47)>>, + [47]), + + ?T(<<57:0>>, + []), + + ?T(<<"apa">>, + "apa"), + + ?T(<<1:3,"string",9:5>>, + [46,110,142,77,45,204,233]), + + ?T(<<>>, + []), + + ?T(<<37.98:64/native-float>>, + native_3798()), + + ?T(<<32978297842987249827298387697777669766334937:128/native-integer>>, + native_bignum()), + + %% Unit tests. + ?T(<<<<5:3>>/bitstring>>, <<5:3>>), + ?T(<<42,<<7:4>>/binary-unit:4>>, <<42,7:4>>), + ?T(<<<<344:17>>/binary-unit:17>>, <<344:17>>), + ?T(<<<<42,3,7656:16>>/binary-unit:16>>, <<42,3,7656:16>>) + + ]. + +native_3798() -> + case <<1:16/native>> of + <<0,1>> -> [64,66,253,112,163,215,10,61]; + <<1,0>> -> [61,10,215,163,112,253,66,64] + end. + +native_bignum() -> + case <<1:16/native>> of + <<0,1>> -> [129,205,18,177,1,213,170,101,39,231,109,128,176,11,73,217]; + <<1,0>> -> [217,73,11,176,128,109,231,39,101,170,213,1,177,18,205,129] + end. + +evaluate(Str, Vars) -> + {ok,Tokens,_} = + erl_scan:string(Str ++ " . "), + {ok, [Expr]} = erl_parse:parse_exprs(Tokens), + case erl_eval:expr(Expr, Vars) of + {value, Result, _} -> + Result + end. + +eval_list([], _Vars) -> + []; +eval_list([{C_bin, Str, Bytes} | Rest], Vars) -> + case catch evaluate(Str, Vars) of + {'EXIT', Error} -> + io:format("Evaluation error: ~p, ~p, ~p~n", [Str, Vars, Error]), + exit(Error); + E_bin -> + [{C_bin, E_bin, Str, Bytes} | eval_list(Rest, Vars)] + end. + +one_test({C_bin, E_bin, Str, Bytes}) when is_list(Bytes) -> + io:format(" ~s, ~p~n", [Str, Bytes]), + Bin = list_to_binary(Bytes), + if + C_bin == Bin -> + ok; + true -> + io:format("ERROR: Compiled: ~p. Expected ~p. Got ~p.~n", + [Str, Bytes, binary_to_list(C_bin)]), + test_server:fail(comp) + end, + if + E_bin == Bin -> + ok; + true -> + io:format("ERROR: Interpreted: ~p. Expected ~p. Got ~p.~n", + [Str, Bytes, binary_to_list(E_bin)]), + test_server:fail(comp) + end; +one_test({C_bin, E_bin, Str, Result}) -> + io:format(" ~s ~p~n", [Str, C_bin]), + if + C_bin == E_bin -> + ok; + true -> + Arbitrary = case Result of + unknown -> + size(C_bin); + _ -> + Result + end, + case equal_lists(binary_to_list(C_bin), + binary_to_list(E_bin), + Arbitrary) of + false -> + io:format("ERROR: Compiled not equal to interpreted:" + "~n ~p, ~p.~n", + [binary_to_list(C_bin), binary_to_list(E_bin)]), + test_server:fail(comp); + 0 -> + ok; + %% For situations where the final bits may not matter, like + %% for floats: + N when is_integer(N) -> + io:format("Info: compiled and interpreted differ in the" + " last bytes:~n ~p, ~p.~n", + [binary_to_list(C_bin), binary_to_list(E_bin)]), + ok + end + end. + +equal_lists([], [], _) -> + 0; +equal_lists([], _, _) -> + false; +equal_lists(_, [], _) -> + false; +equal_lists([A|AR], [A|BR], R) -> + equal_lists(AR, BR, R); +equal_lists(A, B, R) -> + if + length(A) /= length(B) -> + false; + length(A) =< R -> + R; + true -> + false + end. + +fail_check({'EXIT',{badarg,_}}, Str, Vars) -> + try evaluate(Str, Vars) of + Res -> + io:format("Interpreted result: ~p", [Res]), + ?t:fail(did_not_fail_in_intepreted_code) + catch + error:badarg -> + ok + end; +fail_check(Res, _, _) -> + io:format("Compiled result: ~p", [Res]), + ?t:fail(did_not_fail_in_compiled_code). + +%%% Simple working cases +test1(suite) -> []; +test1(Config) when is_list(Config) -> + ?line I_13 = i(13), + ?line I_big1 = big(1), + ?line Vars = [{'I_13', I_13}, + {'I_big1', I_big1}], + ?line lists:foreach(fun one_test/1, eval_list(l(I_13, I_big1), Vars)). + +%%% Misc + +%%% <<A:S, A:(N-S)>> +comp(N, A, S) -> + M1 = (1 bsl S) - 1, + M2 = (1 bsl (N-S)) - 1, + [((A band M1) bsl (N-S)) bor (A band M2)]. + +gen(N, S, A) -> + [?T(<<A:S, A:(N-S)>>, comp(N, A, S))]. + +gen_l(N, S, A) -> + [?T(<<A:S/little, A:(N-S)/little>>, comp(N, A, S))]. + +test2(suite) -> []; +test2(Config) when is_list(Config) -> + ?line test2(0, 8, 2#10101010101010101), + ?line test2(0, 8, 2#1111111111). + +test2(End, End, _) -> + ok; +test2(I, End, A) -> + test2(I, A), + test2(I+1, End, A). + +test2(S, A) -> + N = 8, + Vars = [{'A',A}, {'N',N}, {'S',S}], + io:format("Vars: ~p\n", [Vars]), + lists:foreach(fun one_test/1, eval_list(gen(N, S, A), Vars)), + lists:foreach(fun one_test/1, eval_list(gen_l(N, S, A), Vars)). + +%%% Tests without facit + +t3() -> + [?N(<<4711:13, 9876:13, 3:6>>), + ?N(<<4.57:64/float>>), + ?N(<<4.57:32/float>>), + + ?N(<<>>) + ]. + +test3(suite) -> []; +test3(Config) when is_list(Config) -> + ?line Vars = [], + ?line lists:foreach(fun one_test/1, eval_list(t3(), Vars)). + +gen_u(N, S, A) -> + [?N(<<A:S, A:(N-S)>>)]. + +gen_u_l(N, S, A) -> + [?N(<<A:S/little, A:(N-S)/little>>)]. + +test4(suite) -> []; +test4(Config) when is_list(Config) -> + ?line test4(0, 16, 2#10101010101010101), + ?line test4(0, 16, 2#1111111111). + +test4(End, End, _) -> + ok; +test4(I, End, A) -> + test4(I, A), + test4(I+1, End, A). + +test4(S, A) -> + N = 16, + Vars = [{'A', A}, {'N', 16}, {'S', S}], + lists:foreach(fun one_test/1, eval_list(gen_u(N, S, A), Vars)), + lists:foreach(fun one_test/1, eval_list(gen_u_l(N, S, A), Vars)). + +gen_b(N, S, A) -> + [?T(<<A:S/binary-unit:1, A:(N-S)/binary-unit:1>>, + binary_to_list(<<A:S/binary-unit:1, A:(N-S)/binary-unit:1>>))]. + +test5(suite) -> []; +test5(doc) -> ["OTP-3995"]; +test5(Config) when is_list(Config) -> + ?line test5(0, 8, <<73>>), + ?line test5(0, 8, <<68>>). + +test5(End, End, _) -> + ok; +test5(I, End, A) -> + test5(I, A), + test5(I+1, End, A). + +test5(S, A) -> + N = 8, + Vars = [{'A', A}, {'N', 8}, {'S', S}], + lists:foreach(fun one_test/1, eval_list(gen_b(N, S, A), Vars)). + +%%% Failure cases +testf(suite) -> []; +testf(Config) when is_list(Config) -> + ?line ?FAIL(<<3.14>>), + ?line ?FAIL(<<<<1,2>>>>), + + ?line ?FAIL(<<2.71/binary>>), + ?line ?FAIL(<<24334/binary>>), + ?line ?FAIL(<<24334344294788947129487129487219847/binary>>), + BigInt = id(24334344294788947129487129487219847), + ?line ?FAIL_VARS(<<BigInt/binary>>, [{'BigInt',BigInt}]), + ?line ?FAIL_VARS(<<42,BigInt/binary>>, [{'BigInt',BigInt}]), + ?line ?FAIL_VARS(<<BigInt:2/binary>>, [{'BigInt',BigInt}]), + + %% One negative field size, but the sum of field sizes will be 1 byte. + %% Make sure that we reject that properly. + I_minus_777 = id(-777), + I_minus_2047 = id(-2047), + ?line ?FAIL_VARS(<<I_minus_777:2048/unit:8,57:I_minus_2047/unit:8>>, + ordsets:from_list([{'I_minus_777',I_minus_777}, + {'I_minus_2047',I_minus_2047}])), + ?line ?FAIL(<<<<1,2,3>>/float>>), + + %% Negative field widths. + ?line testf_1(-8, <<1,2,3,4,5>>), + ?line ?FAIL(<<0:(-(1 bsl 100))>>), + + ?line ?FAIL(<<42:(-16)>>), + ?line ?FAIL(<<3.14:(-8)/float>>), + ?line ?FAIL(<<<<23,56,0,2>>:(-16)/binary>>), + ?line ?FAIL(<<<<23,56,0,2>>:(2.5)/binary>>), + ?line ?FAIL(<<<<23,56,0,2>>:(anka)>>), + ?line ?FAIL(<<<<23,56,0,2>>:(anka)>>), + + %% Unit failures. + ?line ?FAIL(<<<<1:1>>/binary>>), + Sz = id(1), + ?line ?FAIL_VARS(<<<<1:Sz>>/binary>>, [{'Sz',Sz}]), + ?line {'EXIT',{badarg,_}} = (catch <<<<1:(id(1))>>/binary>>), + ?line ?FAIL(<<<<7,8,9>>/binary-unit:16>>), + ?line ?FAIL(<<<<7,8,9,3:7>>/binary-unit:16>>), + ?line ?FAIL(<<<<7,8,9,3:7>>/binary-unit:17>>), + + ok. + +testf_1(W, B) -> + Vars = [{'W',W}], + ?FAIL_VARS(<<42:W>>, Vars), + ?FAIL_VARS(<<3.14:W/float>>, Vars), + ?FAIL_VARS(<<B:W/binary>>, [{'B',B}|Vars]). + +not_used(doc) -> + "Test that constructed binaries that are not used will still give an exception."; +not_used(Config) when is_list(Config) -> + ?line ok = not_used1(3, <<"dum">>), + ?line {'EXIT',{badarg,_}} = (catch not_used1(3, "dum")), + ?line {'EXIT',{badarg,_}} = (catch not_used2(444, -2)), + ?line {'EXIT',{badarg,_}} = (catch not_used2(444, anka)), + ?line {'EXIT',{badarg,_}} = (catch not_used3(444)), + ok. + +not_used1(I, BinString) -> + <<I:32,BinString/binary>>, + ok. + +not_used2(I, Sz) -> + <<I:Sz>>, + ok. + +not_used3(I) -> + <<I:(-8)>>, + ok. + +in_guard(Config) when is_list(Config) -> + ?line 1 = in_guard(<<16#74ad:16>>, 16#e95, 5), + ?line 2 = in_guard(<<16#3A,16#F7,"hello">>, 16#3AF7, <<"hello">>), + ?line 3 = in_guard(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415), + nope = in_guard(<<1>>, 42, b), + nope = in_guard(<<1>>, a, b), + nope = in_guard(<<1,2>>, 1, 1), + nope = in_guard(<<4,5>>, 1, 2.71), + nope = in_guard(<<4,5>>, 1, <<12,13>>), + ok. + +in_guard(Bin, A, B) when <<A:13,B:3>> == Bin -> 1; +in_guard(Bin, A, B) when <<A:16,B/binary>> == Bin -> 2; +in_guard(Bin, A, B) when <<A:14,B/float,3:2>> == Bin -> 3; +in_guard(Bin, A, B) when {a,b,<<A:14,B/float,3:2>>} == Bin -> cant_happen; +in_guard(_, _, _) -> nope. + +mem_leak(doc) -> "Make sure that construction has no memory leak"; +mem_leak(Config) when is_list(Config) -> + ?line B = make_bin(16, <<0>>), + ?line mem_leak(1024, B), + ok. + +mem_leak(0, _) -> ok; +mem_leak(N, B) -> + ?line big_bin(B, <<23>>), + ?line {'EXIT',{badarg,_}} = (catch big_bin(B, bad)), + maybe_gc(), + mem_leak(N-1, B). + +big_bin(B1, B2) -> + <<B1/binary,B1/binary,B1/binary,B1/binary, + B1/binary,B1/binary,B1/binary,B1/binary, + B1/binary,B1/binary,B1/binary,B1/binary, + B1/binary,B1/binary,B1/binary,B1/binary, + B2/binary>>. + +make_bin(0, Acc) -> Acc; +make_bin(N, Acc) -> make_bin(N-1, <<Acc/binary,Acc/binary>>). + +maybe_gc() -> + case erlang:system_info(heap_type) of + shared -> erlang:garbage_collect(); + hybrid -> erlang:garbage_collect(); + private -> ok + end. + +-define(COF(Int0), + ?line (fun(Int) -> + true = <<Int:32/float>> =:= <<(float(Int)):32/float>>, + true = <<Int:64/float>> =:= <<(float(Int)):64/float>> + end)(nonliteral(Int0)), + ?line true = <<Int0:32/float>> =:= <<(float(Int0)):32/float>>, + ?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>). + +-define(COF64(Int0), + ?line (fun(Int) -> + true = <<Int:64/float>> =:= <<(float(Int)):64/float>> + end)(nonliteral(Int0)), + ?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>). + +nonliteral(X) -> X. + +coerce_to_float(Config) when is_list(Config) -> + ?COF(0), + ?COF(-1), + ?COF(1), + ?COF(42), + ?COF(255), + ?COF(-255), + ?COF(38474), + ?COF(387498738948729893849444444443), + ?COF(-37489378937773899999999999999993), + ?COF64(298748888888888888888888888883478264866528467367364766666666666666663), + ?COF64(-367546729879999999999947826486652846736736476555566666663), + ok. + +bjorn(Config) when is_list(Config) -> + ?line error = bjorn_1(), + ok. + +bjorn_1() -> + Bitstr = <<7:13>>, + try + do_something() + catch + throw:blurf -> + ignore + end, + do_more(Bitstr, 13). + +do_more(Bin, Sz) -> + %% Previous bug in the bs_bits_to_bytes instruction: The exeption code + %% was not set - the previous exception (throw:blurf) would be used, + %% causing the catch to slip. + try <<Bin:Sz/binary>> of + _V -> ok + catch + error:_ -> + error + end. + +do_something() -> + throw(blurf). + +huge_float_field(Config) when is_list(Config) -> + ?line {'EXIT',{badarg,_}} = (catch <<0.0:9/float-unit:8>>), + ?line huge_float_check(catch <<0.0:67108865/float-unit:64>>), + ?line huge_float_check(catch <<0.0:((1 bsl 26)+1)/float-unit:64>>), + ?line huge_float_check(catch <<0.0:(id(67108865))/float-unit:64>>), +%% ?line huge_float_check(catch <<0.0:((1 bsl 60)+1)/float-unit:64>>), + ?line huge_float_check(catch <<3839739387439387383739387987347983:((1 bsl 26)+1)/float-unit:64>>), +%% ?line huge_float_check(catch <<3839739387439387383739387987347983:((1 bsl 60)+1)/float-unit:64>>), + ok. + +huge_float_check({'EXIT',{system_limit,_}}) -> ok; +huge_float_check({'EXIT',{badarg,_}}) -> ok. + +huge_binary(Config) when is_list(Config) -> + ?line 16777216 = size(<<0:(id(1 bsl 26)),(-1):(id(1 bsl 26))>>), + ok. + +system_limit(Config) when is_list(Config) -> + WordSize = erlang:system_info(wordsize), + BitsPerWord = WordSize * 8, + ?line {'EXIT',{system_limit,_}} = + (catch <<0:(id(0)),42:(id(1 bsl BitsPerWord))>>), + ?line {'EXIT',{system_limit,_}} = + (catch <<42:(id(1 bsl BitsPerWord)),0:(id(0))>>), + ?line {'EXIT',{system_limit,_}} = + (catch <<(id(<<>>))/binary,0:(id(1 bsl 100))>>), + + case WordSize of + 4 -> + system_limit_32(); + 8 -> + ok + end. + +system_limit_32() -> + ?line {'EXIT',{badarg,_}} = (catch <<42:(-1)>>), + ?line {'EXIT',{badarg,_}} = (catch <<42:(id(-1))>>), + ?line {'EXIT',{badarg,_}} = (catch <<42:(id(-389739873536870912))/unit:8>>), + ?line {'EXIT',{system_limit,_}} = (catch <<42:536870912/unit:8>>), + ?line {'EXIT',{system_limit,_}} = (catch <<42:(id(536870912))/unit:8>>), + ?line {'EXIT',{system_limit,_}} = (catch <<0:(id(8)),42:536870912/unit:8>>), + ?line {'EXIT',{system_limit,_}} = + (catch <<0:(id(8)),42:(id(536870912))/unit:8>>), + ok. + +badarg(Config) when is_list(Config) -> + ?line {'EXIT',{badarg,_}} = + (catch <<0:(id(1 bsl 100)),0:(id(-1))>>), + ?line {'EXIT',{badarg,_}} = + (catch <<0:(id(1 bsl 100)),0:(id(-(1 bsl 70)))>>), + ?line {'EXIT',{badarg,_}} = + (catch <<0:(id(-(1 bsl 70))),0:(id(1 bsl 100))>>), + + ?line {'EXIT',{badarg,_}} = + (catch <<(id(<<>>))/binary,0:(id(-(1 bsl 100)))>>), + + ok. + +copy_writable_binary(Config) when is_list(Config) -> + ?line [copy_writable_binary_1(I) || I <- lists:seq(0, 256)], + ok. + +copy_writable_binary_1(_) -> + ?line Bin0 = <<(id(<<>>))/binary,0,1,2,3,4,5,6,7>>, + ?line SubBin = make_sub_bin(Bin0), + ?line id(<<42,34,55,Bin0/binary>>), %Make reallocation likelier. + ?line Pid = spawn(fun() -> + copy_writable_binary_holder(Bin0, SubBin) + end), + ?line Tab = ets:new(holder, []), + ?line ets:insert(Tab, {17,Bin0}), + ?line ets:insert(Tab, {42,SubBin}), + ?line id(<<Bin0/binary,0:(64*1024*8)>>), + ?line Pid ! self(), + ?line [{17,Bin0}] = ets:lookup(Tab, 17), + ?line [{42,Bin0}] = ets:lookup(Tab, 42), + receive + {Pid,Bin0,Bin0} -> ok; + Other -> + io:format("Unexpected message: ~p", [Other]), + ?line ?t:fail() + end, + ok. + +copy_writable_binary_holder(Bin, SubBin) -> + receive + Pid -> + Pid ! {self(),Bin,SubBin} + end. + +make_sub_bin(Bin0) -> + N = bit_size(Bin0), + <<_:17,Bin:N/bitstring,_:5>> = <<(-1):17,Bin0/bitstring,(-1):5>>, + Bin = Bin0, %Assertion. + Bin. + +%% Make sure that bit syntax expression with huge field size are +%% not constructed at compile time. + +kostis(Config) when is_list(Config) -> + case have_250_terabytes_of_ram() of + true -> + Bin = <<0:800000000000>>, + EmbeddedBin = <<0,(<<0:99999999999>>)/bitstring,1>>, + Bin0 = list_to_binary([Bin,Bin,Bin,Bin,Bin]), + Bin1 = list_to_binary([Bin0,Bin0,Bin0,Bin0,Bin0,Bin0]), + Bin2 = list_to_binary([Bin1,Bin1]), + id({EmbeddedBin,Bin0,Bin1,Bin2}); + false -> + ok + end. + +%% I'm not even certain how much 250 TB really is... +%% but I'm sure I don't have it :-) + +have_250_terabytes_of_ram() -> false. + +%% Test that different ways of using bit syntax instructions +%% give the same result. + +dynamic(Config) when is_list(Config) -> + ?line dynamic_1(fun dynamic_big/5), + ?line dynamic_1(fun dynamic_little/5), + ok. + +dynamic_1(Dynamic) -> + <<Lpad:128>> = erlang:md5([0]), + <<Rpad:128>> = erlang:md5([1]), + <<Int:128>> = erlang:md5([2]), + 8385 = dynamic_2(0, {Int,Lpad,Rpad,Dynamic}, 0). + +dynamic_2(129, _, Count) -> Count; +dynamic_2(Bef, Data, Count0) -> + Count = dynamic_3(Bef, 128-Bef, Data, Count0), + dynamic_2(Bef+1, Data, Count). + +dynamic_3(_, -1, _, Count) -> Count; +dynamic_3(Bef, N, {Int0,Lpad,Rpad,Dynamic}=Data, Count) -> + Int1 = Int0 band ((1 bsl (N+3))-1), + Dynamic(Bef, N, Int1, Lpad, Rpad), + Dynamic(Bef, N, -Int1, Lpad, Rpad), + + %% OTP-7085: Test a small number in a wide field. + Int2 = Int0 band 16#FFFFFF, + Dynamic(Bef, N, Int2, Lpad, Rpad), + Dynamic(Bef, N, -Int2, Lpad, Rpad), + dynamic_3(Bef, N-1, Data, Count+1). + +dynamic_big(Bef, N, Int, Lpad, Rpad) -> + NumBin = id(<<Int:N>>), + MaskedInt = Int band ((1 bsl N) - 1), + <<MaskedInt:N>> = NumBin, + + %% Construct the binary in two different ways. + Bin = id(<<Lpad:Bef,NumBin/bitstring,Rpad:(128-Bef-N)>>), + Bin = <<Lpad:Bef,Int:N,Rpad:(128-Bef-N)>>, + + %% Further verify the result by matching. + LpadMasked = Lpad band ((1 bsl Bef) - 1), + RpadMasked = Rpad band ((1 bsl (128-Bef-N)) - 1), + Rbits = (128-Bef-N), + <<LpadMasked:Bef,MaskedInt:N,RpadMasked:Rbits>> = id(Bin), + ok. + +dynamic_little(Bef, N, Int, Lpad, Rpad) -> + NumBin = id(<<Int:N/little>>), + MaskedInt = Int band ((1 bsl N) - 1), + <<MaskedInt:N/little>> = NumBin, + + %% Construct the binary in two different ways. + Bin = id(<<Lpad:Bef/little,NumBin/bitstring,Rpad:(128-Bef-N)/little>>), + Bin = <<Lpad:Bef/little,Int:N/little,Rpad:(128-Bef-N)/little>>, + + %% Further verify the result by matching. + LpadMasked = Lpad band ((1 bsl Bef) - 1), + RpadMasked = Rpad band ((1 bsl (128-Bef-N)) - 1), + Rbits = (128-Bef-N), + <<LpadMasked:Bef/little,MaskedInt:N/little,RpadMasked:Rbits/little>> = id(Bin), + ok. + +%% Test that the bs_add/5 instruction handles big numbers correctly. +bs_add(Config) when is_list(Config) -> + Mod = bs_construct_bs_add, + N = 2000, + Code = [{module, Mod}, + {exports, [{bs_add,2}]}, + {labels, 2}, + + %% bs_add(Number, -SmallestBig) -> Number + N + {function, bs_add, 2, 2}, + {label,1}, + {func_info,{atom,Mod},{atom,bs_add},2}, + + {label,2}, + {move,{x,0},{x,2}}] ++ + lists:duplicate(N-1, {bs_add,{f,0},[{x,2},{integer,1},1],{x,2}}) ++ + [{gc_bif,abs,{f,0},3,[{x,1}],{x,4}}, %Force GC, ignore result. + {gc_bif,'+',{f,0},3,[{x,2},{integer,1}],{x,0}}, %Safe result in {x,0} + return], + + %% Write assembly file and assemble it. + ?line PrivDir = ?config(priv_dir, Config), + ?line RootName = filename:join(PrivDir, atom_to_list(Mod)), + ?line AsmFile = RootName ++ ".S", + ?line {ok,Fd} = file:open(AsmFile, [write]), + ?line [io:format(Fd, "~p. \n", [T]) || T <- Code], + ?line ok = file:close(Fd), + ?line {ok,Mod} = compile:file(AsmFile, [from_asm,report,{outdir,PrivDir}]), + ?line LoadRc = code:load_abs(RootName), + ?line {module,_Module} = LoadRc, + + %% Find smallest positive bignum. + ?line SmallestBig = smallest_big(), + ?line io:format("~p\n", [SmallestBig]), + ?line Expected = SmallestBig + N, + DoTest = fun() -> + exit(Mod:bs_add(SmallestBig, -SmallestBig)) + end, + ?line {Pid,Mref} = spawn_monitor(DoTest), + receive + {'DOWN',Mref,process,Pid,Res} -> ok + end, + ?line Expected = Res, + + %% Clean up. + ?line ok = file:delete(AsmFile), + ?line ok = file:delete(code:which(Mod)), + ok. + + +smallest_big() -> + smallest_big_1(1 bsl 24). + +smallest_big_1(N) -> + case erts_debug:flat_size(N) of + 0 -> smallest_big_1(N+N); + _ -> N + end. + +otp_7422(Config) when is_list(Config) -> + otp_7422_int(0), + otp_7422_bin(0). + +otp_7422_int(N) when N < 512 -> + T = erlang:make_tuple(N, []), + spawn_link(fun() -> + id(T), + %% A size of field 0 would write one byte beyond + %% the current position in the binary. It could + %% overwrite the continuation pointer stored on + %% the stack if HTOP was equal to E (the stack pointer). + id(<<0:(id(0))>>) + end), + otp_7422_int(N+1); +otp_7422_int(_) -> ok. + +otp_7422_bin(N) when N < 512 -> + T = erlang:make_tuple(N, []), + Z = id(<<>>), + spawn_link(fun() -> + id(T), + id(<<Z:(id(0))/bits>>) + end), + otp_7422_bin(N+1); +otp_7422_bin(_) -> ok. + +id(I) -> I. diff --git a/erts/emulator/test/bs_match_bin_SUITE.erl b/erts/emulator/test/bs_match_bin_SUITE.erl new file mode 100644 index 0000000000..3d054a279f --- /dev/null +++ b/erts/emulator/test/bs_match_bin_SUITE.erl @@ -0,0 +1,195 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(bs_match_bin_SUITE). + +-export([all/1,byte_split_binary/1,bit_split_binary/1,match_huge_bin/1]). + +-include("test_server.hrl"). + +all(suite) -> + [byte_split_binary,bit_split_binary,match_huge_bin]. + +byte_split_binary(doc) -> "Tries to split a binary at all byte-aligned positions."; +byte_split_binary(Config) when is_list(Config) -> + ?line L = lists:seq(0, 57), + ?line B = mkbin(L), + ?line byte_split(L, B, size(B)), + ?line Unaligned = make_unaligned_sub_binary(B), + ?line byte_split(L, Unaligned, size(Unaligned)). + +byte_split(L, B, Pos) when Pos >= 0 -> + ?line Sz1 = Pos, + ?line Sz2 = size(B) - Pos, + ?line <<B1:Sz1/binary,B2:Sz2/binary>> = B, + ?line B1 = list_to_binary(lists:sublist(L, 1, Pos)), + ?line B2 = list_to_binary(lists:nthtail(Pos, L)), + ?line byte_split(L, B, Pos-1); +byte_split(_, _, _) -> ok. + +bit_split_binary(doc) -> "Tries to split a binary at all positions."; +bit_split_binary(Config) when is_list(Config) -> + Fun = fun(Bin, List, SkipBef, N) -> + ?line SkipAft = 8*size(Bin) - N - SkipBef, + %%io:format("~p, ~p, ~p", [SkipBef,N,SkipAft]), + ?line <<_:SkipBef,OutBin:N/binary-unit:1,_:SkipAft>> = Bin, + ?line OutBin = make_bin_from_list(List, N) + end, + ?line bit_split_binary1(Fun, erlang:md5(<<1,2,3>>)), + ?line bit_split_binary1(Fun, + make_unaligned_sub_binary(erlang:md5(<<1,2,3>>))), + ok. + +bit_split_binary1(Action, Bin) -> + BitList = bits_to_list(binary_to_list(Bin), 16#80), + bit_split_binary2(Action, Bin, BitList, 0). + +bit_split_binary2(Action, Bin, [_|T]=List, Bef) -> + bit_split_binary3(Action, Bin, List, Bef, size(Bin)*8), + bit_split_binary2(Action, Bin, T, Bef+1); +bit_split_binary2(_, _, [], _) -> ok. + +bit_split_binary3(Action, Bin, List, Bef, Aft) when Bef =< Aft -> + Action(Bin, List, Bef, (Aft-Bef) div 8 * 8), + bit_split_binary3(Action, Bin, List, Bef, Aft-8); +bit_split_binary3(_, _, _, _, _) -> ok. + +make_bin_from_list(_, 0) -> mkbin([]); +make_bin_from_list(List, N) -> + list_to_binary([make_int(List, 8, 0), + make_bin_from_list(lists:nthtail(8, List), N-8)]). + + +make_int(_, 0, Acc) -> Acc; +make_int([H|T], N, Acc) -> make_int(T, N-1, Acc bsl 1 bor H). + +bits_to_list([_|T], 0) -> bits_to_list(T, 16#80); +bits_to_list([H|_]=List, Mask) -> + [case H band Mask of + 0 -> 0; + _ -> 1 + end|bits_to_list(List, Mask bsr 1)]; +bits_to_list([], _) -> []. + +mkbin(L) when is_list(L) -> list_to_binary(L). + +make_unaligned_sub_binary(Bin0) -> + Bin1 = <<0:3,Bin0/binary,31:5>>, + Sz = size(Bin0), + <<0:3,Bin:Sz/binary,31:5>> = id(Bin1), + Bin. + +id(I) -> I. + +match_huge_bin(Config) when is_list(Config) -> + ?line Bin = <<0:(1 bsl 27),13:8>>, + ?line skip_huge_bin_1(1 bsl 27, Bin), + ?line 16777216 = match_huge_bin_1(1 bsl 27, Bin), + + %% Test overflowing the size of a binary field. + ?line nomatch = overflow_huge_bin_skip_32(Bin), + ?line nomatch = overflow_huge_bin_32(Bin), + ?line nomatch = overflow_huge_bin_skip_64(Bin), + ?line nomatch = overflow_huge_bin_64(Bin), + + %% Size in variable + ?line ok = overflow_huge_bin(Bin, lists:seq(25, 32)++lists:seq(50, 64)), + ?line ok = overflow_huge_bin_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)), + + ok. + +overflow_huge_bin(Bin, [Sz0|Sizes]) -> + Sz = id(1 bsl Sz0), + case Bin of + <<_:Sz/binary-unit:8,0,_/binary>> -> + {error,Sz}; + _ -> + case Bin of + <<NewBin:Sz/binary-unit:8,0,_/binary>> -> + {error,Sz,size(NewBin)}; + _ -> + overflow_huge_bin(Bin, Sizes) + end + end; +overflow_huge_bin(_, []) -> ok. + +overflow_huge_bin_unit128(Bin, [Sz0|Sizes]) -> + Sz = id(1 bsl Sz0), + case Bin of + <<_:Sz/binary-unit:128,0,_/binary>> -> + {error,Sz}; + _ -> + case Bin of + <<NewBin:Sz/binary-unit:128,0,_/binary>> -> + {error,Sz,size(NewBin)}; + _ -> + overflow_huge_bin_unit128(Bin, Sizes) + end + end; +overflow_huge_bin_unit128(_, []) -> ok. + +skip_huge_bin_1(I, Bin) -> + <<_:I/binary-unit:1,13>> = Bin, + ok. + +match_huge_bin_1(I, Bin) -> + case Bin of + <<Val:I/binary-unit:1,13>> -> size(Val); + _ -> nomatch + end. + +overflow_huge_bin_skip_32(<<_:4294967296/binary,0,_/binary>>) -> 1; % 1 bsl 32 +overflow_huge_bin_skip_32(<<_:33554432/binary-unit:128,0,_/binary>>) -> 2; % 1 bsl 25 +overflow_huge_bin_skip_32(<<_:67108864/binary-unit:64,0,_/binary>>) -> 3; % 1 bsl 26 +overflow_huge_bin_skip_32(<<_:134217728/binary-unit:32,0,_/binary>>) -> 4; % 1 bsl 27 +overflow_huge_bin_skip_32(<<_:268435456/binary-unit:16,0,_/binary>>) -> 5; % 1 bsl 28 +overflow_huge_bin_skip_32(<<_:536870912/binary-unit:8,0,_/binary>>) -> 6; % 1 bsl 29 +overflow_huge_bin_skip_32(<<_:1073741824/binary-unit:8,0,_/binary>>) -> 7; % 1 bsl 30 +overflow_huge_bin_skip_32(<<_:2147483648/binary-unit:8,0,_/binary>>) -> 8; % 1 bsl 31 +overflow_huge_bin_skip_32(_) -> nomatch. + +overflow_huge_bin_32(<<Bin:4294967296/binary,_/binary>>) -> {1,Bin}; % 1 bsl 32 +overflow_huge_bin_32(<<Bin:33554432/binary-unit:128,0,_/binary>>) -> {2,Bin}; % 1 bsl 25 +overflow_huge_bin_32(<<Bin:67108864/binary-unit:128,0,_/binary>>) -> {3,Bin}; % 1 bsl 26 +overflow_huge_bin_32(<<Bin:134217728/binary-unit:128,0,_/binary>>) -> {4,Bin}; % 1 bsl 27 +overflow_huge_bin_32(<<Bin:268435456/binary-unit:128,0,_/binary>>) -> {5,Bin}; % 1 bsl 28 +overflow_huge_bin_32(<<Bin:536870912/binary-unit:128,0,_/binary>>) -> {6,Bin}; % 1 bsl 29 +overflow_huge_bin_32(<<Bin:1073741824/binary-unit:128,0,_/binary>>) -> {7,Bin}; % 1 bsl 30 +overflow_huge_bin_32(<<Bin:2147483648/binary-unit:128,0,_/binary>>) -> {8,Bin}; % 1 bsl 31 +overflow_huge_bin_32(_) -> nomatch. + +overflow_huge_bin_skip_64(<<_:18446744073709551616/binary,0,_/binary>>) -> 1; % 1 bsl 64 +overflow_huge_bin_skip_64(<<_:144115188075855872/binary-unit:128,0,_/binary>>) -> 2; % 1 bsl 57 +overflow_huge_bin_skip_64(<<_:288230376151711744/binary-unit:64,0,_/binary>>) -> 3; % 1 bsl 58 +overflow_huge_bin_skip_64(<<_:576460752303423488/binary-unit:32,0,_/binary>>) -> 4; % 1 bsl 59 +overflow_huge_bin_skip_64(<<_:1152921504606846976/binary-unit:16,0,_/binary>>) -> 5; % 1 bsl 60 +overflow_huge_bin_skip_64(<<_:2305843009213693952/binary-unit:8,0,_/binary>>) -> 6; % 1 bsl 61 +overflow_huge_bin_skip_64(<<_:4611686018427387904/binary-unit:8,0,_/binary>>) -> 7; % 1 bsl 62 +overflow_huge_bin_skip_64(<<_:9223372036854775808/binary-unit:8,_/binary>>) -> 8; % 1 bsl 63 +overflow_huge_bin_skip_64(_) -> nomatch. + +overflow_huge_bin_64(<<Bin:18446744073709551616/binary,_/binary>>) -> {1,Bin}; % 1 bsl 64 +overflow_huge_bin_64(<<Bin:144115188075855872/binary-unit:128,0,_/binary>>) -> {2,Bin}; % 1 bsl 57 +overflow_huge_bin_64(<<Bin:288230376151711744/binary-unit:128,0,_/binary>>) -> {3,Bin}; % 1 bsl 58 +overflow_huge_bin_64(<<Bin:576460752303423488/binary-unit:128,0,_/binary>>) -> {4,Bin}; % 1 bsl 59 +overflow_huge_bin_64(<<Bin:1152921504606846976/binary-unit:128,0,_/binary>>) -> {5,Bin}; % 1 bsl 60 +overflow_huge_bin_64(<<Bin:2305843009213693952/binary-unit:128,0,_/binary>>) -> {6,Bin}; % 1 bsl 61 +overflow_huge_bin_64(<<Bin:4611686018427387904/binary-unit:128,0,_/binary>>) -> {7,Bin}; % 1 bsl 62 +overflow_huge_bin_64(<<Bin:9223372036854775808/binary-unit:128,0,_/binary>>) -> {8,Bin}; % 1 bsl 63 +overflow_huge_bin_64(_) -> nomatch. diff --git a/erts/emulator/test/bs_match_int_SUITE.erl b/erts/emulator/test/bs_match_int_SUITE.erl new file mode 100644 index 0000000000..99dee7c7bc --- /dev/null +++ b/erts/emulator/test/bs_match_int_SUITE.erl @@ -0,0 +1,331 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(bs_match_int_SUITE). + +-export([all/1,integer/1,signed_integer/1,dynamic/1,more_dynamic/1,mml/1, + match_huge_int/1,bignum/1,unaligned_32_bit/1]). + +-include("test_server.hrl"). + +-import(lists, [seq/2]). + +all(suite) -> + [integer,signed_integer,dynamic,more_dynamic,mml,match_huge_int,bignum, + unaligned_32_bit]. + +integer(Config) when is_list(Config) -> + ?line 0 = get_int(mkbin([])), + ?line 0 = get_int(mkbin([0])), + ?line 42 = get_int(mkbin([42])), + ?line 255 = get_int(mkbin([255])), + ?line 256 = get_int(mkbin([1,0])), + ?line 257 = get_int(mkbin([1,1])), + ?line 258 = get_int(mkbin([1,2])), + ?line 258 = get_int(mkbin([1,2])), + ?line 65534 = get_int(mkbin([255,254])), + ?line 16776455 = get_int(mkbin([255,253,7])), + ?line 4245492555 = get_int(mkbin([253,13,19,75])), + ?line 4294967294 = get_int(mkbin([255,255,255,254])), + ?line 4294967295 = get_int(mkbin([255,255,255,255])), + ?line Eight = [200,1,19,128,222,42,97,111], + ?line cmp128(Eight, uint(Eight)), + ?line fun_clause(catch get_int(mkbin(seq(1,5)))), + ok. + +get_int(Bin) -> + I = get_int1(Bin), + get_int(Bin, I). + +get_int(Bin0, I) when size(Bin0) < 4 -> + Bin = <<0,Bin0/binary>>, + I = get_int1(Bin), + get_int(Bin, I); +get_int(_, I) -> I. + +get_int1(<<I:0>>) -> I; +get_int1(<<I:8>>) -> I; +get_int1(<<I:16>>) -> I; +get_int1(<<I:24>>) -> I; +get_int1(<<I:32>>) -> I. + +cmp128(<<I:128>>, I) -> equal; +cmp128(_, _) -> not_equal. + +signed_integer(Config) when is_list(Config) -> + ?line {no_match,_} = sint(mkbin([])), + ?line {no_match,_} = sint(mkbin([1,2,3])), + ?line 127 = sint(mkbin([127])), + ?line -1 = sint(mkbin([255])), + ?line -128 = sint(mkbin([128])), + ?line 42 = sint(mkbin([42,255])), + ?line 127 = sint(mkbin([127,255])). + +sint(Bin) -> + case Bin of + <<I:8/signed>> -> I; + <<I:8/signed,_:3,_:5>> -> I; + Other -> {no_match,Other} + end. + +uint(L) -> uint(L, 0). +uint([H|T], Acc) -> uint(T, Acc bsl 8 bor H); +uint([], Acc) -> Acc. + +dynamic(Config) when is_list(Config) -> + dynamic(mkbin([255]), 8), + dynamic(mkbin([255,255]), 16), + dynamic(mkbin([255,255,255]), 24), + dynamic(mkbin([255,255,255,255]), 32), + ok. + +dynamic(Bin, S1) when S1 >= 0 -> + S2 = size(Bin) * 8 - S1, + dynamic(Bin, S1, S2, (1 bsl S1) - 1, (1 bsl S2) - 1), + dynamic(Bin, S1-1); +dynamic(_, _) -> ok. + +dynamic(Bin, S1, S2, A, B) -> +% io:format("~p ~p ~p ~p\n", [S1,S2,A,B]), + case Bin of + <<A:S1,B:S2>> -> + io:format("~p ~p ~p ~p\n", [S1,S2,A,B]), + ok; + _Other -> erlang:error(badmatch, [Bin,S1,S2,A,B]) + end. + +more_dynamic(doc) -> "Extract integers at different alignments and of different sizes."; +more_dynamic(Config) when is_list(Config) -> + + % Unsigned big-endian numbers. + Unsigned = fun(Bin, List, SkipBef, N) -> + SkipAft = 8*size(Bin) - N - SkipBef, + <<_:SkipBef,Int:N,_:SkipAft>> = Bin, + Int = make_int(List, N, 0) + end, + ?line more_dynamic1(Unsigned, erlang:md5(mkbin([42]))), + + %% Signed big-endian numbers. + Signed = fun(Bin, List, SkipBef, N) -> + SkipAft = 8*size(Bin) - N - SkipBef, + <<_:SkipBef,Int:N/signed,_:SkipAft>> = Bin, + case make_signed_int(List, N) of + Int -> ok; + Other -> + io:format("Bin = ~p,", [Bin]), + io:format("SkipBef = ~p, N = ~p", [SkipBef,N]), + io:format("Expected ~p, got ~p", [Int,Other]), + ?t:fail() + end + end, + ?line more_dynamic1(Signed, erlang:md5(mkbin([43]))), + + %% Unsigned little-endian numbers. + UnsLittle = fun(Bin, List, SkipBef, N) -> + SkipAft = 8*size(Bin) - N - SkipBef, + <<_:SkipBef,Int:N/little,_:SkipAft>> = Bin, + Int = make_int(big_to_little(List, N), N, 0) + end, + ?line more_dynamic1(UnsLittle, erlang:md5(mkbin([44]))), + + %% Signed little-endian numbers. + SignLittle = fun(Bin, List, SkipBef, N) -> + SkipAft = 8*size(Bin) - N - SkipBef, + <<_:SkipBef,Int:N/signed-little,_:SkipAft>> = Bin, + Little = big_to_little(List, N), + Int = make_signed_int(Little, N) + end, + ?line more_dynamic1(SignLittle, erlang:md5(mkbin([45]))), + + ok. + +more_dynamic1(Action, Bin) -> + BitList = bits_to_list(binary_to_list(Bin), 16#80), + more_dynamic2(Action, Bin, BitList, 0). + +more_dynamic2(Action, Bin, [_|T]=List, Bef) -> + more_dynamic3(Action, Bin, List, Bef, size(Bin)*8), + more_dynamic2(Action, Bin, T, Bef+1); +more_dynamic2(_, _, [], _) -> ok. + +more_dynamic3(Action, Bin, List, Bef, Aft) when Bef =< Aft -> +%% io:format("~p, ~p", [Bef,Aft-Bef]), + Action(Bin, List, Bef, Aft-Bef), + more_dynamic3(Action, Bin, List, Bef, Aft-1); +more_dynamic3(_, _, _, _, _) -> ok. + +big_to_little(List, N) -> big_to_little(List, N, []). + +big_to_little([B0,B1,B2,B3,B4,B5,B6,B7|T], N, Acc) when N >= 8 -> + big_to_little(T, N-8, [B0,B1,B2,B3,B4,B5,B6,B7|Acc]); +big_to_little(List, N, Acc) -> lists:sublist(List, 1, N) ++ Acc. + +make_signed_int(_List, 0) -> 0; +make_signed_int([0|_]=List, N) -> make_int(List, N, 0); +make_signed_int([1|_]=List0, N) -> + List1 = reversed_sublist(List0, N, []), + List2 = two_complement_and_reverse(List1, 1, []), + -make_int(List2, length(List2), 0). + +reversed_sublist(_List, 0, Acc) -> Acc; +reversed_sublist([H|T], N, Acc) -> reversed_sublist(T, N-1, [H|Acc]). + +two_complement_and_reverse([H|T], Carry, Acc) -> + Sum = 1-H+Carry, + two_complement_and_reverse(T, Sum div 2, [Sum rem 2|Acc]); +two_complement_and_reverse([], Carry, Acc) -> [Carry|Acc]. + +make_int(_List, 0, Acc) -> Acc; +make_int([H|T], N, Acc) -> make_int(T, N-1, Acc bsl 1 bor H). + +bits_to_list([_|T], 0) -> bits_to_list(T, 16#80); +bits_to_list([H|_]=List, Mask) -> + [case H band Mask of + 0 -> 0; + _ -> 1 + end|bits_to_list(List, Mask bsr 1)]; +bits_to_list([], _) -> []. + +fun_clause({'EXIT',{function_clause,_}}) -> ok. +mkbin(L) when is_list(L) -> list_to_binary(L). + + +mml(Config) when is_list(Config) -> + ?line single_byte_binary = mml_choose(<<42>>), + ?line multi_byte_binary = mml_choose(<<42,43>>). + +mml_choose(<<_A:8>>) -> single_byte_binary; +mml_choose(<<_A:8,_T/binary>>) -> multi_byte_binary. + +match_huge_int(Config) when is_list(Config) -> + Sz = 1 bsl 27, + ?line Bin = <<0:Sz,13:8>>, + ?line skip_huge_int_1(Sz, Bin), + ?line 0 = match_huge_int_1(Sz, Bin), + + %% Test overflowing the size of an integer field. + ?line nomatch = overflow_huge_int_skip_32(Bin), + case erlang:system_info(wordsize) of + 4 -> + ?line nomatch = overflow_huge_int_32(Bin); + 8 -> + %% An attempt will be made to allocate heap space for + %% the bignum (which will probably fail); only if the + %% allocation succeds will the matching fail because + %% the binary is too small. + ok + end, + ?line nomatch = overflow_huge_int_skip_64(Bin), + ?line nomatch = overflow_huge_int_64(Bin), + + %% Test overflowing the size of an integer field using variables as sizes. + ?line Sizes = case erlang:system_info(wordsize) of + 4 -> lists:seq(25, 32); + 8 -> [] + end ++ lists:seq(50, 64), + ?line ok = overflow_huge_int_unit128(Bin, Sizes), + + ok. + +overflow_huge_int_unit128(Bin, [Sz0|Sizes]) -> + Sz = id(1 bsl Sz0), + case Bin of + <<_:Sz/unit:128,0,_/binary>> -> + {error,Sz}; + _ -> + case Bin of + <<Var:Sz/unit:128,0,_/binary>> -> + {error,Sz,Var}; + _ -> + overflow_huge_int_unit128(Bin, Sizes) + end + end; +overflow_huge_int_unit128(_, []) -> ok. + +match_huge_int_1(I, Bin) -> + <<Int:I,13>> = Bin, + Int. + +skip_huge_int_1(I, Bin) -> + <<_:I,13>> = Bin. + +overflow_huge_int_skip_32(<<_:4294967296,0,_/binary>>) -> 1; % 1 bsl 32 +overflow_huge_int_skip_32(<<_:33554432/unit:128,0,_/binary>>) -> 2; % 1 bsl 25 +overflow_huge_int_skip_32(<<_:67108864/unit:64,0,_/binary>>) -> 3; % 1 bsl 26 +overflow_huge_int_skip_32(<<_:134217728/unit:32,0,_/binary>>) -> 4; % 1 bsl 27 +overflow_huge_int_skip_32(<<_:268435456/unit:16,0,_/binary>>) -> 5; % 1 bsl 28 +overflow_huge_int_skip_32(<<_:536870912/unit:8,0,_/binary>>) -> 6; % 1 bsl 29 +overflow_huge_int_skip_32(<<_:1073741824/unit:8,0,_/binary>>) -> 7; % 1 bsl 30 +overflow_huge_int_skip_32(<<_:2147483648/unit:8,0,_/binary>>) -> 8; % 1 bsl 31 +overflow_huge_int_skip_32(_) -> nomatch. + +overflow_huge_int_32(<<Int:4294967296,_/binary>>) -> {1,Int}; % 1 bsl 32 +overflow_huge_int_32(<<Int:33554432/unit:128,0,_/binary>>) -> {2,Int}; % 1 bsl 25 +overflow_huge_int_32(<<Int:67108864/unit:128,0,_/binary>>) -> {3,Int}; % 1 bsl 26 +overflow_huge_int_32(<<Int:134217728/unit:128,0,_/binary>>) -> {4,Int}; % 1 bsl 27 +overflow_huge_int_32(<<Int:268435456/unit:128,0,_/binary>>) -> {5,Int}; % 1 bsl 28 +overflow_huge_int_32(<<Int:536870912/unit:128,0,_/binary>>) -> {6,Int}; % 1 bsl 29 +overflow_huge_int_32(<<Int:1073741824/unit:128,0,_/binary>>) -> {7,Int}; % 1 bsl 30 +overflow_huge_int_32(<<Int:2147483648/unit:128,0,_/binary>>) -> {8,Int}; % 1 bsl 31 +overflow_huge_int_32(_) -> nomatch. + +overflow_huge_int_skip_64(<<_:18446744073709551616,_/binary>>) -> 1; % 1 bsl 64 +overflow_huge_int_skip_64(<<_:144115188075855872/unit:128,0,_/binary>>) -> 2; % 1 bsl 57 +overflow_huge_int_skip_64(<<_:288230376151711744/unit:64,0,_/binary>>) -> 3; % 1 bsl 58 +overflow_huge_int_skip_64(<<_:576460752303423488/unit:32,0,_/binary>>) -> 4; % 1 bsl 59 +overflow_huge_int_skip_64(<<_:1152921504606846976/unit:16,0,_/binary>>) -> 5; % 1 bsl 60 +overflow_huge_int_skip_64(<<_:2305843009213693952/unit:8,0,_/binary>>) -> 6; % 1 bsl 61 +overflow_huge_int_skip_64(<<_:4611686018427387904/unit:8,0,_/binary>>) -> 7; % 1 bsl 62 +overflow_huge_int_skip_64(<<_:9223372036854775808/unit:8,0,_/binary>>) -> 8; % 1 bsl 63 +overflow_huge_int_skip_64(_) -> nomatch. + +overflow_huge_int_64(<<Int:18446744073709551616,_/binary>>) -> {1,Int}; % 1 bsl 64 +overflow_huge_int_64(<<Int:144115188075855872/unit:128,0,_/binary>>) -> {2,Int}; % 1 bsl 57 +overflow_huge_int_64(<<Int:288230376151711744/unit:128,0,_/binary>>) -> {3,Int}; % 1 bsl 58 +overflow_huge_int_64(<<Int:576460752303423488/unit:128,0,_/binary>>) -> {4,Int}; % 1 bsl 59 +overflow_huge_int_64(<<Int:1152921504606846976/unit:128,0,_/binary>>) -> {5,Int}; % 1 bsl 60 +overflow_huge_int_64(<<Int:2305843009213693952/unit:128,0,_/binary>>) -> {6,Int}; % 1 bsl 61 +overflow_huge_int_64(<<Int:4611686018427387904/unit:128,0,_/binary>>) -> {7,Int}; % 1 bsl 62 +overflow_huge_int_64(<<Int:9223372036854775808/unit:128,0,_/binary>>) -> {8,Int}; % 1 bsl 63 +overflow_huge_int_64(_) -> nomatch. + +bignum(Config) when is_list(Config) -> + ?line Bin = id(<<42,0:1024/unit:8,43>>), + ?line <<42:1025/little-integer-unit:8,_:8>> = Bin, + ?line <<_:8,43:1025/integer-unit:8>> = Bin, + + ?line BignumBin = id(<<0:512/unit:8,258254417031933722623:9/unit:8>>), + ?line <<258254417031933722623:(512+9)/unit:8>> = BignumBin, + erlang:garbage_collect(), %Search for holes in debug-build. + ok. + +unaligned_32_bit(Config) when is_list(Config) -> + %% There used to be a risk for heap overflow (fixed in R11B-5). + ?line L = unaligned_32_bit_1(<<-1:(64*1024)>>), + ?line unaligned_32_bit_verify(L, 1638). + +unaligned_32_bit_1(<<1:1,U:32,_:7,T/binary>>) -> + [U|unaligned_32_bit_1(T)]; +unaligned_32_bit_1(_) -> + []. + +unaligned_32_bit_verify([], 0) -> ok; +unaligned_32_bit_verify([4294967295|T], N) when N > 0 -> + unaligned_32_bit_verify(T, N-1). + +id(I) -> I. diff --git a/erts/emulator/test/bs_match_misc_SUITE.erl b/erts/emulator/test/bs_match_misc_SUITE.erl new file mode 100644 index 0000000000..6de2ef67e5 --- /dev/null +++ b/erts/emulator/test/bs_match_misc_SUITE.erl @@ -0,0 +1,537 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(bs_match_misc_SUITE). + +-export([all/1,bound_var/1,bound_tail/1,t_float/1,little_float/1,sean/1, + kenneth/1,encode_binary/1,native/1,happi/1, + size_var/1,wiger/1,x0_context/1,huge_float_field/1, + writable_binary_matched/1,otp_7198/1]). + +-include("test_server.hrl"). + +all(suite) -> + [bound_var,bound_tail,t_float,little_float,sean, + kenneth,encode_binary,native,happi, + size_var,wiger,x0_context,huge_float_field, + writable_binary_matched,otp_7198]. + +bound_var(doc) -> "Test matching of bound variables."; +bound_var(Config) when is_list(Config) -> + ?line ok = bound_var(42, 13, <<42,13>>), + ?line nope = bound_var(42, 13, <<42,255>>), + ?line nope = bound_var(42, 13, <<154,255>>), + ok. + +bound_var(A, B, <<A:8,B:8>>) -> ok; +bound_var(_, _, _) -> nope. + +bound_tail(doc) -> "Test matching of a bound tail."; +bound_tail(Config) when is_list(Config) -> + ?line ok = bound_tail(<<>>, <<13,14>>), + ?line ok = bound_tail(<<2,3>>, <<1,1,2,3>>), + ?line nope = bound_tail(<<2,3>>, <<1,1,2,7>>), + ?line nope = bound_tail(<<2,3>>, <<1,1,2,3,4>>), + ?line nope = bound_tail(<<2,3>>, <<>>), + ok. + +bound_tail(T, <<_:16,T/binary>>) -> ok; +bound_tail(_, _) -> nope. + +t_float(Config) when is_list(Config) -> + F = f1(), + G = f_one(), + + ?line G = match_float(<<63,128,0,0>>, 32, 0), + ?line G = match_float(<<63,240,0,0,0,0,0,0>>, 64, 0), + + ?line fcmp(F, match_float(<<F:32/float>>, 32, 0)), + ?line fcmp(F, match_float(<<F:64/float>>, 64, 0)), + ?line fcmp(F, match_float(<<1:1,F:32/float,127:7>>, 32, 1)), + ?line fcmp(F, match_float(<<1:1,F:64/float,127:7>>, 64, 1)), + ?line fcmp(F, match_float(<<1:13,F:32/float,127:3>>, 32, 13)), + ?line fcmp(F, match_float(<<1:13,F:64/float,127:3>>, 64, 13)), + + ?line {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16, 0)), + ?line {'EXIT',{{badmatch,_},_}} = (catch match_float(<<0,0>>, 16#7fffffff, 0)), + + ok. + + +fcmp(F1, F2) when (F1 - F2) / F2 < 0.0000001 -> ok. + +match_float(Bin0, Fsz, I) -> + Bin = make_sub_bin(Bin0), + Bsz = size(Bin) * 8, + Tsz = Bsz - Fsz - I, + <<_:I,F:Fsz/float,_:Tsz>> = Bin, + F. + +little_float(Config) when is_list(Config) -> + F = f2(), + G = f_one(), + + ?line G = match_float_little(<<0,0,0,0,0,0,240,63>>, 64, 0), + ?line G = match_float_little(<<0,0,128,63>>, 32, 0), + + ?line fcmp(F, match_float_little(<<F:32/float-little>>, 32, 0)), + ?line fcmp(F, match_float_little(<<F:64/float-little>>, 64, 0)), + ?line fcmp(F, match_float_little(<<1:1,F:32/float-little,127:7>>, 32, 1)), + ?line fcmp(F, match_float_little(<<1:1,F:64/float-little,127:7>>, 64, 1)), + ?line fcmp(F, match_float_little(<<1:13,F:32/float-little,127:3>>, 32, 13)), + ?line fcmp(F, match_float_little(<<1:13,F:64/float-little,127:3>>, 64, 13)), + + ok. + +match_float_little(Bin0, Fsz, I) -> + Bin = make_sub_bin(Bin0), + Bsz = size(Bin) * 8, + Tsz = Bsz - Fsz - I, + <<_:I,F:Fsz/float-little,_:Tsz>> = Bin, + F. + + +make_sub_bin(Bin0) -> + Sz = size(Bin0), + Bin1 = <<37,Bin0/binary,38,39>>, + <<_:8,Bin:Sz/binary,_:8,_:8>> = Bin1, + Bin. + +f1() -> + 3.1415. + +f2() -> + 2.7133. + +f_one() -> + 1.0. + +sean(Config) when is_list(Config) -> + ?line small = sean1(<<>>), + ?line small = sean1(<<1>>), + ?line small = sean1(<<1,2>>), + ?line small = sean1(<<1,2,3>>), + ?line large = sean1(<<1,2,3,4>>), + + ?line small = sean1(<<4>>), + ?line small = sean1(<<4,5>>), + ?line small = sean1(<<4,5,6>>), + ?line {'EXIT',{function_clause,_}} = (catch sean1(<<4,5,6,7>>)), + ok. + +sean1(<<B/binary>>) when byte_size(B) < 4 -> small; +sean1(<<1, _B/binary>>) -> large. + +kenneth(Config) when is_list(Config) -> + {ok,[145,148,113,129,0,0,0,0]} = + msisdn_internal_storage(<<145,148,113,129,0,0,0,0>>, []). + +msisdn_internal_storage(<<>>,MSISDN) -> + {ok,lists:reverse(MSISDN)}; +msisdn_internal_storage(<<2#11111111:8,_Rest/binary>>,MSISDN) -> + {ok,lists:reverse(MSISDN)}; +msisdn_internal_storage(<<2#1111:4,DigitN:4,_Rest/binary>>,MSISDN) when + DigitN < 10 -> + {ok,lists:reverse([(DigitN bor 2#11110000)|MSISDN])}; +msisdn_internal_storage(<<DigitNplus1:4,DigitN:4,Rest/binary>>,MSISDN) when + DigitNplus1 < 10, + DigitN < 10 -> + NewMSISDN=[((DigitNplus1 bsl 4) bor DigitN)|MSISDN], + msisdn_internal_storage(Rest,NewMSISDN); +msisdn_internal_storage(_Rest,_MSISDN) -> + {fault}. %% Mandatory IE incorrect + +encode_binary(Config) when is_list(Config) -> + "C2J2QiSc" = encodeBinary(<<11,98,118,66,36,156>>, []), + ok. + +encodeBinary(<<>>, Output) -> + lists:reverse(Output); +encodeBinary(<<Data:1/binary>>, Output) -> + <<DChar1:6, DChar2:2>> = Data, + Char1 = getBase64Char(DChar1), + Char2 = getBase64Char(DChar2), + Char3 = "=", + Char4 = "=", + NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output, + encodeBinary(<<>>, NewOutput); +encodeBinary(<<Data:2/binary>>, Output) -> + <<DChar1:6, DChar2:6, DChar3:4>> = Data, + Char1 = getBase64Char(DChar1), + Char2 = getBase64Char(DChar2), + Char3 = getBase64Char(DChar3), + Char4 = "=", + NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output, + encodeBinary(<<>>, NewOutput); +encodeBinary(<<Data:3/binary, Rest/binary>>, Output) -> + <<DChar1:6, DChar2:6, DChar3:6, DChar4:6>> = Data, + Char1 = getBase64Char(DChar1), + Char2 = getBase64Char(DChar2), + Char3 = getBase64Char(DChar3), + Char4 = getBase64Char(DChar4), + NewOutput = Char4 ++ Char3 ++ Char2 ++ Char1 ++ Output, + encodeBinary(Rest, NewOutput); +encodeBinary(_Data, _) -> + error. + +getBase64Char(0) -> "A"; +getBase64Char(1) -> "B"; +getBase64Char(2) -> "C"; +getBase64Char(3) -> "D"; +getBase64Char(4) -> "E"; +getBase64Char(5) -> "F"; +getBase64Char(6) -> "G"; +getBase64Char(7) -> "H"; +getBase64Char(8) -> "I"; +getBase64Char(9) -> "J"; +getBase64Char(10) -> "K"; +getBase64Char(11) -> "L"; +getBase64Char(12) -> "M"; +getBase64Char(13) -> "N"; +getBase64Char(14) -> "O"; +getBase64Char(15) -> "P"; +getBase64Char(16) -> "Q"; +getBase64Char(17) -> "R"; +getBase64Char(18) -> "S"; +getBase64Char(19) -> "T"; +getBase64Char(20) -> "U"; +getBase64Char(21) -> "V"; +getBase64Char(22) -> "W"; +getBase64Char(23) -> "X"; +getBase64Char(24) -> "Y"; +getBase64Char(25) -> "Z"; +getBase64Char(26) -> "a"; +getBase64Char(27) -> "b"; +getBase64Char(28) -> "c"; +getBase64Char(29) -> "d"; +getBase64Char(30) -> "e"; +getBase64Char(31) -> "f"; +getBase64Char(32) -> "g"; +getBase64Char(33) -> "h"; +getBase64Char(34) -> "i"; +getBase64Char(35) -> "j"; +getBase64Char(36) -> "k"; +getBase64Char(37) -> "l"; +getBase64Char(38) -> "m"; +getBase64Char(39) -> "n"; +getBase64Char(40) -> "o"; +getBase64Char(41) -> "p"; +getBase64Char(42) -> "q"; +getBase64Char(43) -> "r"; +getBase64Char(44) -> "s"; +getBase64Char(45) -> "t"; +getBase64Char(46) -> "u"; +getBase64Char(47) -> "v"; +getBase64Char(48) -> "w"; +getBase64Char(49) -> "x"; +getBase64Char(50) -> "y"; +getBase64Char(51) -> "z"; +getBase64Char(52) -> "0"; +getBase64Char(53) -> "1"; +getBase64Char(54) -> "2"; +getBase64Char(55) -> "3"; +getBase64Char(56) -> "4"; +getBase64Char(57) -> "5"; +getBase64Char(58) -> "6"; +getBase64Char(59) -> "7"; +getBase64Char(60) -> "8"; +getBase64Char(61) -> "9"; +getBase64Char(62) -> "+"; +getBase64Char(63) -> "/"; +getBase64Char(_Else) -> + %% This is an illegal input. +% cgLogEM:log(error, ?MODULE, getBase64Char, [Else], +% "illegal input", +% ?LINE, version()), + "**". + +-define(M(F), <<F>> = <<F>>). + +native(Config) when is_list(Config) -> + ?line ?M(3.14:64/native-float), + ?line ?M(333:16/native), + ?line ?M(38658345:32/native), + case <<1:16/native>> of + <<0,1>> -> native_big(); + <<1,0>> -> native_little() + end. + +native_big() -> + ?line <<37.33:64/native-float>> = <<37.33:64/big-float>>, + ?line <<3974:16/native-integer>> = <<3974:16/big-integer>>, + {comment,"Big endian"}. + +native_little() -> + ?line <<37869.32343:64/native-float>> = <<37869.32343:64/little-float>>, + ?line <<7974:16/native-integer>> = <<7974:16/little-integer>>, + {comment,"Little endian"}. + +happi(Config) when is_list(Config) -> + Bin = <<".123">>, + ?line <<"123">> = lex_digits1(Bin, 1, []), + ?line <<"123">> = lex_digits2(Bin, 1, []), + ok. + +lex_digits1(<<$., Rest/binary>>,_Val,_Acc) -> + Rest; +lex_digits1(<<N, Rest/binary>>,Val, Acc) when N >= $0 , N =< $9 -> + lex_digits1(Rest,Val*10+dec(N),Acc); +lex_digits1(_Other,_Val,_Acc) -> + not_ok. + +lex_digits2(<<N, Rest/binary>>,Val, Acc) when N >= $0 , N =< $9 -> + lex_digits2(Rest,Val*10+dec(N),Acc); +lex_digits2(<<$., Rest/binary>>,_Val,_Acc) -> + Rest; +lex_digits2(_Other,_Val,_Acc) -> + not_ok. + +dec(A) -> + A-$0. + +size_var(Config) when is_list(Config) -> + ?line {<<45>>,<<>>} = split(<<1:16,45>>), + ?line {<<45>>,<<46,47>>} = split(<<1:16,45,46,47>>), + ?line {<<45,46>>,<<47>>} = split(<<2:16,45,46,47>>), + + ?line {<<45,46,47>>,<<48>>} = split_2(<<16:8,3:16,45,46,47,48>>), + + ?line {<<45,46>>,<<47>>} = split(2, <<2:16,45,46,47>>), + ?line {'EXIT',{function_clause,_}} = (catch split(42, <<2:16,45,46,47>>)), + + ?line <<"cdef">> = skip(<<2:8,"abcdef">>), + + ok. + +split(<<N:16,B:N/binary,T/binary>>) -> + {B,T}. + +split(N, <<N:16,B:N/binary,T/binary>>) -> + {B,T}. + +split_2(<<N0:8,N:N0,B:N/binary,T/binary>>) -> + {B,T}. + +skip(<<N:8,_:N/binary,T/binary>>) -> T. + +wiger(Config) when is_list(Config) -> + ?line ok1 = wcheck(<<3>>), + ?line ok2 = wcheck(<<1,2,3>>), + ?line ok3 = wcheck(<<4>>), + ?line {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>), + ?line {error,<<>>} = wcheck(<<>>), + ok. + +wcheck(<<A>>) when A==3-> + ok1; +wcheck(<<_,_:2/binary>>) -> + ok2; +wcheck(<<_>>) -> + ok3; +wcheck(Other) -> + {error,Other}. + +%% Test that having the match context in x(0) works. + +x0_context(Config) when is_list(Config) -> + x0_0([], <<3.0:64/float,42:16,123456:32>>). + +x0_0(_, Bin) -> + <<3.0:64/float,42:16,_/binary>> = Bin, + x0_1([], Bin, 64, 16, 2). + +x0_1(_, Bin, FloatSz, IntSz, BinSz) -> + <<_:FloatSz/float,42:IntSz,B:BinSz/binary,C:1/binary,D/binary>> = Bin, + id({B,C,D}), + <<_:FloatSz/float,42:IntSz,B:BinSz/binary,_/binary>> = Bin, + x0_2([], Bin). + +x0_2(_, Bin) -> + <<_:64,0:7,42:9,_/binary>> = Bin, + x0_3([], Bin). + +x0_3(_, Bin) -> + case Bin of + <<_:72,7:8,_/binary>> -> + ?line ?t:fail(); + <<_:64,0:16,_/binary>> -> + ?line ?t:fail(); + <<_:64,42:16,123456:32,_/binary>> -> + ok + end. + + +huge_float_field(Config) when is_list(Config) -> + Sz = 1 bsl 27, + ?line Bin = <<0:Sz>>, + + ?line nomatch = overflow_huge_float_skip_32(Bin), + ?line nomatch = overflow_huge_float_32(Bin), + + ?line ok = overflow_huge_float(Bin, lists:seq(25, 32)++lists:seq(50, 64)), + ?line ok = overflow_huge_float_unit128(Bin, lists:seq(25, 32)++lists:seq(50, 64)), + ok. + +overflow_huge_float_skip_32(<<_:4294967296/float,0,_/binary>>) -> 1; % 1 bsl 32 +overflow_huge_float_skip_32(<<_:33554432/float-unit:128,0,_/binary>>) -> 2; % 1 bsl 25 +overflow_huge_float_skip_32(<<_:67108864/float-unit:64,0,_/binary>>) -> 3; % 1 bsl 26 +overflow_huge_float_skip_32(<<_:134217728/float-unit:32,0,_/binary>>) -> 4; % 1 bsl 27 +overflow_huge_float_skip_32(<<_:268435456/float-unit:16,0,_/binary>>) -> 5; % 1 bsl 28 +overflow_huge_float_skip_32(<<_:536870912/float-unit:8,0,_/binary>>) -> 6; % 1 bsl 29 +overflow_huge_float_skip_32(<<_:1073741824/float-unit:8,0,_/binary>>) -> 7; % 1 bsl 30 +overflow_huge_float_skip_32(<<_:2147483648/float-unit:8,0,_/binary>>) -> 8; % 1 bsl 31 +overflow_huge_float_skip_32(_) -> nomatch. + +overflow_huge_float_32(<<F:4294967296/float,_/binary>>) -> {1,F}; % 1 bsl 32 +overflow_huge_float_32(<<F:33554432/float-unit:128,0,_/binary>>) -> {2,F}; % 1 bsl 25 +overflow_huge_float_32(<<F:67108864/float-unit:128,0,_/binary>>) -> {3,F}; % 1 bsl 26 +overflow_huge_float_32(<<F:134217728/float-unit:128,0,_/binary>>) -> {4,F}; % 1 bsl 27 +overflow_huge_float_32(<<F:268435456/float-unit:128,0,_/binary>>) -> {5,F}; % 1 bsl 28 +overflow_huge_float_32(<<F:536870912/float-unit:128,0,_/binary>>) -> {6,F}; % 1 bsl 29 +overflow_huge_float_32(<<F:1073741824/float-unit:128,0,_/binary>>) -> {7,F}; % 1 bsl 30 +overflow_huge_float_32(<<F:2147483648/float-unit:128,0,_/binary>>) -> {8,F}; % 1 bsl 31 +overflow_huge_float_32(_) -> nomatch. + + +overflow_huge_float(Bin, [Sz0|Sizes]) -> + Sz = id(1 bsl Sz0), + case Bin of + <<_:Sz/float-unit:8,0,_/binary>> -> + {error,Sz}; + _ -> + case Bin of + <<Var:Sz/float-unit:8,0,_/binary>> -> + {error,Sz,Var}; + _ -> + overflow_huge_float(Bin, Sizes) + end + end; +overflow_huge_float(_, []) -> ok. + +overflow_huge_float_unit128(Bin, [Sz0|Sizes]) -> + Sz = id(1 bsl Sz0), + case Bin of + <<_:Sz/float-unit:128,0,_/binary>> -> + {error,Sz}; + _ -> + case Bin of + <<Var:Sz/float-unit:128,0,_/binary>> -> + {error,Sz,Var}; + _ -> + overflow_huge_float_unit128(Bin, Sizes) + end + end; +overflow_huge_float_unit128(_, []) -> ok. + + +%% +%% Test that a writable binary can be safely matched. +%% + +writable_binary_matched(Config) when is_list(Config) -> + ?line WritableBin = create_writeable_binary(), + ?line writable_binary_matched(WritableBin, WritableBin, 500). + +writable_binary_matched(<<0>>, _, N) -> + if + N =:= 0 -> ok; + true -> + put(grow_heap, [N|get(grow_heap)]), + ?line WritableBin = create_writeable_binary(), + ?line writable_binary_matched(WritableBin, WritableBin, N-1) + end; +writable_binary_matched(<<B:8,T/binary>>, WritableBin0, N) -> + ?line WritableBin = writable_binary(WritableBin0, B), + writable_binary_matched(T, WritableBin, N). + +writable_binary(WritableBin0, B) when is_binary(WritableBin0) -> + %% Heavy append to force the binary to move. + ?line WritableBin = <<WritableBin0/binary,0:(size(WritableBin0))/unit:8,B>>, + ?line id(<<(id(0)):128/unit:8>>), + WritableBin. + +create_writeable_binary() -> + <<(id(<<>>))/binary,1,2,3,4,5,6,0>>. + +otp_7198(Config) when is_list(Config) -> + %% When a match context was reused, and grown at the same time to + %% increase the number of saved positions, the thing word was not updated + %% to account for the new size. Therefore, if there was a garbage collection, + %% the new slots would be included in the garbage collection. + ?line [do_otp_7198(FillerSize) || FillerSize <- lists:seq(0, 256)], + ok. + +do_otp_7198(FillerSize) -> + Filler = erlang:make_tuple(FillerSize, 42), + {Pid,Ref} = spawn_monitor(fun() -> do_otp_7198_test(Filler) end), + receive + {'DOWN',Ref,process,Pid,normal} -> + ok; + {'DOWN',Ref,process,Pid,Reason} -> + io:format("unexpected: ~p", [Reason]), + ?line ?t:fail() + end. + +do_otp_7198_test(_) -> + [{'KEYWORD',114}, + {'KEYWORD',101}, + {'KEYWORD',103}, + {'KEYWORD',105}, + {'KEYWORD',111}, + {'FIELD',110}, + {'KEYWORD',119}, + {'KEYWORD',104}, + {'KEYWORD',97}, + {'KEYWORD',116}, + {'KEYWORD',101}, + {'KEYWORD',118}, + {'KEYWORD',101}, + {'KEYWORD',114}, + '$thats_all_folks$'] = otp_7198_scan(<<"region:whatever">>, []). + + +otp_7198_scan(<<>>, TokAcc) -> + lists:reverse(['$thats_all_folks$' | TokAcc]); + +otp_7198_scan(<<D, Z, Rest/binary>>, TokAcc) when + (D =:= $D orelse D =:= $d) and + ((Z =:= $\s) or (Z =:= $() or (Z =:= $))) -> + otp_7198_scan(<<Z, Rest/binary>>, ['AND' | TokAcc]); + +otp_7198_scan(<<D>>, TokAcc) when + (D =:= $D) or (D =:= $d) -> + otp_7198_scan(<<>>, ['AND' | TokAcc]); + +otp_7198_scan(<<N, Z, Rest/binary>>, TokAcc) when + (N =:= $N orelse N =:= $n) and + ((Z =:= $\s) or (Z =:= $() or (Z =:= $))) -> + otp_7198_scan(<<Z, Rest/binary>>, ['NOT' | TokAcc]); + +otp_7198_scan(<<C, Rest/binary>>, TokAcc) when + (C >= $A) and (C =< $Z); + (C >= $a) and (C =< $z); + (C >= $0) and (C =< $9) -> + case Rest of + <<$:, R/binary>> -> + otp_7198_scan(R, [{'FIELD', C} | TokAcc]); + _ -> + otp_7198_scan(Rest, [{'KEYWORD', C} | TokAcc]) + end. + + +id(I) -> I. diff --git a/erts/emulator/test/bs_match_tail_SUITE.erl b/erts/emulator/test/bs_match_tail_SUITE.erl new file mode 100644 index 0000000000..b0b0779b65 --- /dev/null +++ b/erts/emulator/test/bs_match_tail_SUITE.erl @@ -0,0 +1,87 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(bs_match_tail_SUITE). + +-author('[email protected]'). +-export([all/1,aligned/1,unaligned/1,zero_tail/1]). + +-include("test_server.hrl"). + +all(suite) -> [aligned,unaligned,zero_tail]. + +aligned(doc) -> "Test aligned tails."; +aligned(Config) when is_list(Config) -> + ?line Tail1 = mkbin([]), + ?line {258,Tail1} = al_get_tail_used(mkbin([1,2])), + ?line Tail2 = mkbin(lists:seq(1, 127)), + ?line {35091,Tail2} = al_get_tail_used(mkbin([137,19|Tail2])), + + ?line 64896 = al_get_tail_unused(mkbin([253,128])), + ?line 64895 = al_get_tail_unused(mkbin([253,127|lists:seq(42, 255)])), + + ?line Tail3 = mkbin(lists:seq(0, 19)), + ?line {0,Tail1} = get_dyn_tail_used(Tail1, 0), + ?line {0,Tail3} = get_dyn_tail_used(mkbin([Tail3]), 0), + ?line {73,Tail3} = get_dyn_tail_used(mkbin([73|Tail3]), 8), + + ?line 0 = get_dyn_tail_unused(mkbin([]), 0), + ?line 233 = get_dyn_tail_unused(mkbin([233]), 8), + ?line 23 = get_dyn_tail_unused(mkbin([23,22,2]), 8), + ok. + +al_get_tail_used(<<A:16,T/binary>>) -> {A,T}. +al_get_tail_unused(<<A:16,_/binary>>) -> A. + +unaligned(doc) -> "Test that an non-aligned tail cannot be matched out."; +unaligned(Config) when is_list(Config) -> + ?line {'EXIT',{function_clause,_}} = (catch get_tail_used(mkbin([42]))), + ?line {'EXIT',{{badmatch,_},_}} = (catch get_dyn_tail_used(mkbin([137]), 3)), + ?line {'EXIT',{function_clause,_}} = (catch get_tail_unused(mkbin([42,33]))), + ?line {'EXIT',{{badmatch,_},_}} = (catch get_dyn_tail_unused(mkbin([44]), 7)), + ok. + +get_tail_used(<<A:1,T/binary>>) -> {A,T}. + +get_tail_unused(<<A:15,_/binary>>) -> A. + +get_dyn_tail_used(Bin, Sz) -> + <<A:Sz,T/binary>> = Bin, + {A,T}. + +get_dyn_tail_unused(Bin, Sz) -> + <<A:Sz,_/binary>> = Bin, + A. + +zero_tail(doc) -> "Test that zero tails are tested correctly."; +zero_tail(Config) when is_list(Config) -> + ?line 7 = (catch test_zero_tail(mkbin([7]))), + ?line {'EXIT',{function_clause,_}} = (catch test_zero_tail(mkbin([1,2]))), + ?line {'EXIT',{function_clause,_}} = (catch test_zero_tail2(mkbin([1,2,3]))), + ok. + +test_zero_tail(<<A:8>>) -> A. + +test_zero_tail2(<<_A:4,_B:4>>) -> ok. + +mkbin(L) when is_list(L) -> list_to_binary(L). + + + + diff --git a/erts/emulator/test/bs_utf_SUITE.erl b/erts/emulator/test/bs_utf_SUITE.erl new file mode 100644 index 0000000000..87adc5197b --- /dev/null +++ b/erts/emulator/test/bs_utf_SUITE.erl @@ -0,0 +1,394 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(bs_utf_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + utf8_roundtrip/1,utf16_roundtrip/1,utf32_roundtrip/1, + utf8_illegal_sequences/1,utf16_illegal_sequences/1, + utf32_illegal_sequences/1, + bad_construction/1]). + +-include("test_server.hrl"). + +-define(FAIL(Expr), ?line fail_check(catch Expr, ??Expr, [])). + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog = ?t:timetrap(?t:minutes(6)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +all(suite) -> + [utf8_roundtrip,utf16_roundtrip,utf32_roundtrip, + utf8_illegal_sequences,utf16_illegal_sequences, + utf32_illegal_sequences,bad_construction]. + +utf8_roundtrip(Config) when is_list(Config) -> + ?line utf8_roundtrip(0, 16#D7FF), + ?line utf8_roundtrip(16#E000, 16#FFFD), + ?line utf8_roundtrip(16#10000, 16#10FFFF), + ok. + +utf8_roundtrip(First, Last) when First =< Last -> + Bin = int_to_utf8(First), + Bin = id(<<First/utf8>>), + Bin = id(<<(id(<<>>))/binary,First/utf8>>), + Unaligned = id(<<3:2,First/utf8>>), + <<_:2,Bin/binary>> = Unaligned, + <<First/utf8>> = Bin, + <<First/utf8>> = make_unaligned(Bin), + utf8_roundtrip(First+1, Last); +utf8_roundtrip(_, _) -> ok. + +utf16_roundtrip(Config) when is_list(Config) -> + Big = fun utf16_big_roundtrip/1, + Little = fun utf16_little_roundtrip/1, + PidRefs = [spawn_monitor(fun() -> + do_utf16_roundtrip(Fun) + end) || Fun <- [Big,Little]], + [receive {'DOWN',Ref,process,Pid,Reason} -> normal=Reason end || + {Pid,Ref} <- PidRefs], + ok. + +do_utf16_roundtrip(Fun) -> + do_utf16_roundtrip(0, 16#D7FF, Fun), + do_utf16_roundtrip(16#E000, 16#FFFD, Fun), + do_utf16_roundtrip(16#10000, 16#10FFFF, Fun). + +do_utf16_roundtrip(First, Last, Fun) when First =< Last -> + Fun(First), + do_utf16_roundtrip(First+1, Last, Fun); +do_utf16_roundtrip(_, _, _) -> ok. + +utf16_big_roundtrip(Char) -> + Bin = id(<<Char/utf16>>), + Bin = id(<<(id(<<>>))/binary,Char/utf16>>), + Unaligned = id(<<3:2,Char/utf16>>), + <<_:2,Bin/binary>> = Unaligned, + <<Char/utf16>> = Bin, + <<Char/utf16>> = make_unaligned(Bin), + ok. + +utf16_little_roundtrip(Char) -> + Bin = id(<<Char/little-utf16>>), + Bin = id(<<(id(<<>>))/binary,Char/little-utf16>>), + Unaligned = id(<<3:2,Char/little-utf16>>), + <<_:2,Bin/binary>> = Unaligned, + <<Char/little-utf16>> = Bin, + <<Char/little-utf16>> = make_unaligned(Bin), + ok. + +utf32_roundtrip(Config) when is_list(Config) -> + Big = fun utf32_big_roundtrip/1, + Little = fun utf32_little_roundtrip/1, + PidRefs = [spawn_monitor(fun() -> + do_utf32_roundtrip(Fun) + end) || Fun <- [Big,Little]], + [receive {'DOWN',Ref,process,Pid,Reason} -> normal=Reason end || + {Pid,Ref} <- PidRefs], + ok. + +do_utf32_roundtrip(Fun) -> + do_utf32_roundtrip(0, 16#D7FF, Fun), + do_utf32_roundtrip(16#E000, 16#FFFD, Fun), + do_utf32_roundtrip(16#10000, 16#10FFFF, Fun). + +do_utf32_roundtrip(First, Last, Fun) when First =< Last -> + Fun(First), + do_utf32_roundtrip(First+1, Last, Fun); +do_utf32_roundtrip(_, _, _) -> ok. + +utf32_big_roundtrip(Char) -> + Bin = id(<<Char/utf32>>), + Bin = id(<<(id(<<>>))/binary,Char/utf32>>), + Unaligned = id(<<3:2,Char/utf32>>), + <<_:2,Bin/binary>> = Unaligned, + <<Char/utf32>> = Bin, + <<Char/utf32>> = make_unaligned(Bin), + ok. + +utf32_little_roundtrip(Char) -> + Bin = id(<<Char/little-utf32>>), + Bin = id(<<(id(<<>>))/binary,Char/little-utf32>>), + Unaligned = id(<<3:2,Char/little-utf32>>), + <<_:2,Bin/binary>> = Unaligned, + <<Char/little-utf32>> = Bin, + <<Char/little-utf32>> = make_unaligned(Bin), + ok. + +utf8_illegal_sequences(Config) when is_list(Config) -> + ?line fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large. + ?line fail_range(16#D800, 16#DFFF), %Reserved for UTF-16. + ?line fail_range(16#FFFE, 16#FFFF), %Non-characters. + + %% Illegal first character. + ?line [fail(<<I,16#8F,16#8F,16#8F>>) || I <- lists:seq(16#80, 16#BF)], + + %% Short sequences. + ?line short_sequences(16#80, 16#10FFFF), + + %% Overlong sequences. (Using more bytes than necessary + %% is not allowed.) + ?line overlong(0, 127, 2), + ?line overlong(128, 16#7FF, 3), + ?line overlong(16#800, 16#FFFF, 4), + ok. + +fail_range(Char, End) when Char =< End -> + {'EXIT',_} = (catch <<Char/utf8>>), + Bin = int_to_utf8(Char), + fail(Bin), + fail_range(Char+1, End); +fail_range(_, _) -> ok. + +short_sequences(Char, End) -> + Step = (End - Char) div erlang:system_info(schedulers) + 1, + PidRefs = short_sequences_1(Char, Step, End), + [receive {'DOWN',Ref,process,Pid,Reason} -> normal=Reason end || + {Pid,Ref} <- PidRefs], + ok. + +short_sequences_1(Char, Step, End) when Char =< End -> + CharEnd = lists:min([Char+Step-1,End]), + [spawn_monitor(fun() -> + io:format("~p - ~p\n", [Char,CharEnd]), + do_short_sequences(Char, CharEnd) + end)|short_sequences_1(Char+Step, Step, End)]; +short_sequences_1(_, _, _) -> []. + +do_short_sequences(Char, End) when Char =< End -> + short_sequence(Char), + do_short_sequences(Char+1, End); +do_short_sequences(_, _) -> ok. + +short_sequence(I) -> + case int_to_utf8(I) of + <<S0:3/binary,_:8>> -> + <<S1:2/binary,R1:8>> = S0, + <<S2:1/binary,_:8>> = S1, + fail(S0), + fail(S1), + fail(S2), + fail(<<S2/binary,16#7F,R1,R1>>), + fail(<<S1/binary,16#7F,R1>>), + fail(<<S0/binary,16#7F>>); + <<S0:2/binary,_:8>> -> + <<S1:1/binary,R1:8>> = S0, + fail(S0), + fail(S1), + fail(<<S0/binary,16#7F>>), + fail(<<S1/binary,16#7F>>), + fail(<<S1/binary,16#7F,R1>>); + <<S:1/binary,_:8>> -> + fail(S), + fail(<<S/binary,16#7F>>) + end. + +overlong(Char, Last, NumBytes) when Char =< Last -> + overlong(Char, NumBytes), + overlong(Char+1, Last, NumBytes); +overlong(_, _, _) -> ok. + +overlong(Char, NumBytes) when NumBytes < 5 -> + case int_to_utf8(Char, NumBytes) of + <<Char/utf8>>=Bin -> + ?t:fail({illegal_encoding_accepted,Bin,Char}); + <<OtherChar/utf8>>=Bin -> + ?t:fail({illegal_encoding_accepted,Bin,Char,OtherChar}); + _ -> ok + end, + overlong(Char, NumBytes+1); +overlong(_, _) -> ok. + +fail(Bin) -> + fail_1(Bin), + fail_1(make_unaligned(Bin)). + +fail_1(<<Char/utf8>>=Bin) -> + ?t:fail({illegal_encoding_accepted,Bin,Char}); +fail_1(_) -> ok. + + +utf16_illegal_sequences(Config) when is_list(Config) -> + ?line utf16_fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large. + ?line utf16_fail_range(16#D800, 16#DFFF), %Reserved for UTF-16. + ?line utf16_fail_range(16#FFFE, 16#FFFF), %Non-characters. + + ?line lonely_hi_surrogate(16#D800, 16#DFFF), + ?line leading_lo_surrogate(16#DC00, 16#DFFF), + + ok. + +utf16_fail_range(Char, End) when Char =< End -> + {'EXIT',_} = (catch <<Char/big-utf16>>), + {'EXIT',_} = (catch <<Char/little-utf16>>), + utf16_fail_range(Char+1, End); +utf16_fail_range(_, _) -> ok. + +lonely_hi_surrogate(Char, End) when Char =< End -> + BinBig = <<Char:16/big>>, + BinLittle = <<Char:16/little>>, + case {BinBig,BinLittle} of + {<<Bad/big-utf16>>,_} -> + ?t:fail({lonely_hi_surrogate_accepted,Bad}); + {_,<<Bad/little-utf16>>} -> + ?t:fail({lonely_hi_surrogate_accepted,Bad}); + {_,_} -> + ok + end, + lonely_hi_surrogate(Char+1, End); +lonely_hi_surrogate(_, _) -> ok. + +leading_lo_surrogate(Char, End) when Char =< End -> + leading_lo_surrogate(Char, 16#D800, 16#DFFF), + leading_lo_surrogate(Char+1, End); +leading_lo_surrogate(_, _) -> ok. + +leading_lo_surrogate(HiSurr, LoSurr, End) when LoSurr =< End -> + BinBig = <<HiSurr:16/big,LoSurr:16/big>>, + BinLittle = <<HiSurr:16/little,LoSurr:16/little>>, + case {BinBig,BinLittle} of + {<<Bad/big-utf16,_/bits>>,_} -> + ?t:fail({leading_lo_surrogate_accepted,Bad}); + {_,<<Bad/little-utf16,_/bits>>} -> + ?t:fail({leading_lo_surrogate_accepted,Bad}); + {_,_} -> + ok + end, + leading_lo_surrogate(HiSurr, LoSurr+1, End); +leading_lo_surrogate(_, _, _) -> ok. + +utf32_illegal_sequences(Config) when is_list(Config) -> + ?line utf32_fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large. + ?line utf32_fail_range(16#D800, 16#DFFF), %Reserved for UTF-16. + ?line utf32_fail_range(16#FFFE, 16#FFFF), %Non-characters. + ?line utf32_fail_range(-100, -1), + ok. + +utf32_fail_range(Char, End) when Char =< End -> + {'EXIT',_} = (catch <<Char/big-utf32>>), + {'EXIT',_} = (catch <<Char/little-utf32>>), + case {<<Char:32>>,<<Char:32/little>>} of + {<<Unexpected/utf32>>,_} -> + ?line ?t:fail(Unexpected); + {_,<<Unexpected/little-utf32>>} -> + ?line ?t:fail(Unexpected); + {_,_} -> ok + end, + utf32_fail_range(Char+1, End); +utf32_fail_range(_, _) -> ok. + +bad_construction(Config) when is_list(Config) -> + ?FAIL(<<3.14/utf8>>), + ?FAIL(<<3.1415/utf16>>), + ?FAIL(<<3.1415/utf32>>), + + ?FAIL(<<(-1)/utf8>>), + ?FAIL(<<(-1)/utf16>>), + {'EXIT',_} = (catch <<(id(-1))/utf8>>), + {'EXIT',_} = (catch <<(id(-1))/utf16>>), + {'EXIT',_} = (catch <<(id(-1))/utf32>>), + + ?FAIL(<<16#D800/utf8>>), + ?FAIL(<<16#D800/utf16>>), + ?FAIL(<<16#D800/utf32>>), + + ok. + +%% This function intentionally allows construction of +%% UTF-8 sequence in illegal ranges. +int_to_utf8(I) when I =< 16#7F -> + <<I>>; +int_to_utf8(I) when I =< 16#7FF -> + B2 = I, + B1 = (I bsr 6), + <<1:1,1:1,0:1,B1:5,1:1,0:1,B2:6>>; +int_to_utf8(I) when I =< 16#FFFF -> + B3 = I, + B2 = (I bsr 6), + B1 = (I bsr 12), + <<1:1,1:1,1:1,0:1,B1:4,1:1,0:1,B2:6,1:1,0:1,B3:6>>; +int_to_utf8(I) when I =< 16#3FFFFF -> + B4 = I, + B3 = (I bsr 6), + B2 = (I bsr 12), + B1 = (I bsr 18), + <<1:1,1:1,1:1,1:1,0:1,B1:3,1:1,0:1,B2:6,1:1,0:1,B3:6,1:1,0:1,B4:6>>; +int_to_utf8(I) when I =< 16#3FFFFFF -> + B5 = I, + B4 = (I bsr 6), + B3 = (I bsr 12), + B2 = (I bsr 18), + B1 = (I bsr 24), + <<1:1,1:1,1:1,1:1,1:1,0:1,B1:2,1:1,0:1,B2:6,1:1,0:1,B3:6,1:1,0:1,B4:6, + 1:1,0:1,B5:6>>. + +%% int_to_utf8(I, NumberOfBytes) -> Binary. +%% This function can be used to construct overlong sequences. +int_to_utf8(I, 1) -> + <<I>>; +int_to_utf8(I, 2) -> + B2 = I, + B1 = (I bsr 6), + <<1:1,1:1,0:1,B1:5,1:1,0:1,B2:6>>; +int_to_utf8(I, 3) -> + B3 = I, + B2 = (I bsr 6), + B1 = (I bsr 12), + <<1:1,1:1,1:1,0:1,B1:4,1:1,0:1,B2:6,1:1,0:1,B3:6>>; +int_to_utf8(I, 4) -> + B4 = I, + B3 = (I bsr 6), + B2 = (I bsr 12), + B1 = (I bsr 18), + <<1:1,1:1,1:1,1:1,0:1,B1:3,1:1,0:1,B2:6,1:1,0:1,B3:6,1:1,0:1,B4:6>>. + +make_unaligned(Bin0) when is_binary(Bin0) -> + Bin1 = <<0:3,Bin0/binary,31:5>>, + Sz = byte_size(Bin0), + <<0:3,Bin:Sz/binary,31:5>> = id(Bin1), + Bin. + +fail_check({'EXIT',{badarg,_}}, Str, Vars) -> + try evaluate(Str, Vars) of + Res -> + io:format("Interpreted result: ~p", [Res]), + ?t:fail(did_not_fail_in_intepreted_code) + catch + error:badarg -> + ok + end; +fail_check(Res, _, _) -> + io:format("Compiled result: ~p", [Res]), + ?t:fail(did_not_fail_in_compiled_code). + +evaluate(Str, Vars) -> + {ok,Tokens,_} = + erl_scan:string(Str ++ " . "), + {ok, [Expr]} = erl_parse:parse_exprs(Tokens), + case erl_eval:expr(Expr, Vars) of + {value, Result, _} -> + Result + end. + +id(I) -> I. + diff --git a/erts/emulator/test/busy_port_SUITE.erl b/erts/emulator/test/busy_port_SUITE.erl new file mode 100644 index 0000000000..9b16170293 --- /dev/null +++ b/erts/emulator/test/busy_port_SUITE.erl @@ -0,0 +1,628 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(busy_port_SUITE). + +-export([all/1, io_to_busy/1, message_order/1, send_3/1, + system_monitor/1, no_trap_exit/1, + no_trap_exit_unlinked/1, trap_exit/1, multiple_writers/1, + hard_busy_driver/1, soft_busy_driver/1]). + +-include("test_server.hrl"). + +%% Internal exports. +-export([init/2]). + +all(suite) -> {req, [dynamic_loading], + [io_to_busy, message_order, send_3, + system_monitor, no_trap_exit, + no_trap_exit_unlinked, trap_exit, multiple_writers, + hard_busy_driver, soft_busy_driver]}. + +%% Tests I/O operations to a busy port, to make sure a suspended send +%% operation is correctly restarted. This used to crash Beam. + +io_to_busy(suite) -> []; +io_to_busy(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(30)), + + ?line start_busy_driver(Config), + ?line process_flag(trap_exit, true), + ?line Writer = fun_spawn(fun writer/0), + ?line Generator = fun_spawn(fun() -> generator(100, Writer) end), + ?line wait_for([Writer, Generator]), + + ?line test_server:timetrap_cancel(Dog), + ok. + +generator(N, Writer) -> + generator(N, Writer, lists:duplicate(128, 42)). + +generator(0, Writer, _Data) -> + Writer ! stop, + erlang:garbage_collect(), + receive after 2000 -> ok end, + + %% Calling process_info(Pid, current_function) on a suspended process + %% used to crash Beam. + {current_function, {erlang, send, 2}} = + process_info(Writer, current_function), + unlock_slave(); +generator(N, Writer, Data) -> + Writer ! {exec, Data}, + generator(N-1, Writer, [42|Data]). + +writer() -> + {Owner, Port} = get_slave(), + Port ! {Owner, {connect, self()}}, + X = {a, b, c, d}, + forget({element(1, X), element(2, X), element(3, X), element(4, X)}), + writer_loop(Port). + +writer_loop(Port) -> + receive + {exec, Data} -> + Port ! {self(), {command, Data}}, + writer_loop(Port); + stop -> + erlang:garbage_collect() + end. + +forget(_) -> + ok. + +%% Test the interaction of busy ports and message sending. +%% This used to cause the wrong message to be received. + +message_order(suite) -> {req, dynamic_loading}; +message_order(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + + ?line start_busy_driver(Config), + ?line Self = self(), + ?line Busy = fun_spawn(fun () -> send_to_busy_1(Self) end), + ?line receive after 1000 -> ok end, + ?line Busy ! first, + ?line Busy ! second, + ?line receive after 1 -> ok end, + ?line unlock_slave(), + ?line Busy ! third, + ?line receive + {Busy, first} -> + ok; + Other -> + test_server:fail({unexpected_message, Other}) + end, + + ?line test_server:timetrap_cancel(Dog), + ok. + +send_to_busy_1(Parent) -> + {Owner, Slave} = get_slave(), + Slave ! {Owner, {command, "set_me_busy"}}, + Slave ! {Owner, {command, "hello"}}, + Slave ! {Owner, {command, "hello again"}}, + receive + Message -> + Parent ! {self(), Message} + end. + +%% Test the bif send/3 +send_3(suite) -> {req,dynamic_loading}; +send_3(doc) -> ["Test the BIF send/3"]; +send_3(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + %% + ?line start_busy_driver(Config), + ?line {Owner,Slave} = get_slave(), + ?line ok = erlang:send(Slave, {Owner,{command,"set busy"}}, + [nosuspend]), + ?line nosuspend = erlang:send(Slave, {Owner,{command,"busy"}}, + [nosuspend]), + ?line unlock_slave(), + ?line ok = erlang:send(Slave, {Owner,{command,"not busy"}}, + [nosuspend]), + ?line ok = command(stop), + %% + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Test the erlang:system_monitor(Pid, [busy_port]) +system_monitor(suite) -> {req,dynamic_loading}; +system_monitor(doc) -> ["Test erlang:system_monitor({Pid,[busy_port]})."]; +system_monitor(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Self = self(), + %% + ?line OldMonitor = erlang:system_monitor(Self, [busy_port]), + ?line {Self,[busy_port]} = erlang:system_monitor(), + ?line Void = make_ref(), + ?line start_busy_driver(Config), + ?line {Owner,Slave} = get_slave(), + ?line Master = command(get_master), + ?line Parent = self(), + ?line Busy = + spawn_link( + fun() -> + Slave ! {Owner,{command,"set busy"}}, + receive {Parent,alpha} -> ok end, + Slave ! {Owner,{command,"busy"}}, + Slave ! {Owner,{command,"free"}}, + Parent ! {self(),alpha}, + command(lock), + receive {Parent,beta} -> ok end, + command({port_command,"busy"}), + command({port_command,"free"}), + Parent ! {self(),beta} + end), + ?line Void = rec(Void), + ?line Busy ! {self(),alpha}, + ?line {monitor,Busy,busy_port,Slave} = rec(Void), + ?line unlock_slave(), + ?line {Busy,alpha} = rec(Void), + ?line Void = rec(Void), + ?line Busy ! {self(), beta}, + ?line {monitor,Owner,busy_port,Slave} = rec(Void), + ?line Master ! {Owner, {command, "u"}}, + ?line {Busy,beta} = rec(Void), + ?line Void = rec(Void), + ?line NewMonitor = erlang:system_monitor(OldMonitor), + ?line OldMonitor = erlang:system_monitor(), + ?line OldMonitor = erlang:system_monitor(OldMonitor), + %% + ?line test_server:timetrap_cancel(Dog), + ok. + + + +rec(Tag) -> + receive X -> X after 1000 -> Tag end. + + + + +%% Assuming the following scenario, +%% +%% +---------------+ +-----------+ +%% | process with | | | +%% | no trap_exit |------------------| busy port | +%% | (suspended) | | | +%% +---------------+ +-----------+ +%% +%% tests that the suspended process is killed if the port is killed. + +no_trap_exit(suite) -> []; +no_trap_exit(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line process_flag(trap_exit, true), + ?line Pid = fun_spawn(fun no_trap_exit_process/3, + [self(), linked, Config]), + ?line receive + {Pid, port_created, Port} -> + io:format("Process ~w created port ~w", [Pid, Port]), + ?line exit(Port, die); + Other1 -> + test_server:fail({unexpected_message, Other1}) + end, + ?line receive + {'EXIT', Pid, die} -> + ok; + Other2 -> + test_server:fail({unexpected_message, Other2}) + end, + + ?line test_server:timetrap_cancel(Dog), + ok. + +%% The same scenario as above, but the port has been explicitly +%% unlinked from the process. + +no_trap_exit_unlinked(suite) -> []; +no_trap_exit_unlinked(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line process_flag(trap_exit, true), + ?line Pid = fun_spawn(fun no_trap_exit_process/3, + [self(), unlink, Config]), + ?line receive + {Pid, port_created, Port} -> + io:format("Process ~w created port ~w", [Pid, Port]), + ?line exit(Port, die); + Other1 -> + test_server:fail({unexpected_message, Other1}) + end, + ?line receive + {'EXIT', Pid, normal} -> + ok; + Other2 -> + test_server:fail({unexpected_message, Other2}) + end, + ?line test_server:timetrap_cancel(Dog), + ok. + +no_trap_exit_process(ResultTo, Link, Config) -> + ?line load_busy_driver(Config), + ?line _Master = open_port({spawn, "busy_drv master"}, [eof]), + ?line Slave = open_port({spawn, "busy_drv slave"}, [eof]), + ?line case Link of + linked -> ok; + unlink -> unlink(Slave) + end, + ?line Slave ! {self(), {command, "lock port"}}, + ?line ResultTo ! {self(), port_created, Slave}, + ?line Slave ! {self(), {command, "suspend me"}}, + ok. + +%% Assuming the following scenario, +%% +%% +---------------+ +-----------+ +%% | process with | | | +%% | trap_exit |------------------| busy port | +%% | (suspended) | | | +%% +---------------+ +-----------+ +%% +%% tests that the suspended process is scheduled runnable and +%% receives an 'EXIT' message if the port is killed. + +trap_exit(suite) -> []; +trap_exit(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Pid = fun_spawn(fun busy_port_exit_process/2, [self(), Config]), + ?line receive + {Pid, port_created, Port} -> + io:format("Process ~w created port ~w", [Pid, Port]), + ?line unlink(Pid), + ?line {status, suspended} = process_info(Pid, status), + ?line exit(Port, die); + Other1 -> + test_server:fail({unexpected_message, Other1}) + end, + ?line receive + {Pid, ok} -> + ok; + Other2 -> + test_server:fail({unexpected_message, Other2}) + end, + ?line test_server:timetrap_cancel(Dog), + ok. + +busy_port_exit_process(ResultTo, Config) -> + ?line process_flag(trap_exit, true), + ?line load_busy_driver(Config), + ?line _Master = open_port({spawn, "busy_drv master"}, [eof]), + ?line Slave = open_port({spawn, "busy_drv slave"}, [eof]), + ?line Slave ! {self(), {command, "lock port"}}, + ?line ResultTo ! {self(), port_created, Slave}, + ?line Slave ! {self(), {command, "suspend me"}}, + receive + {'EXIT', Slave, die} -> + ResultTo ! {self(), ok}; + Other -> + ResultTo ! {self(), {unexpected_message, Other}} + end. + +%% Tests that several processes suspended by a write to a busy port +%% will start running as soon as the port becamomes ready. +%% This should work even if some of the processes have terminated +%% in the meantime. + +multiple_writers(suite) -> []; +multiple_writers(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line start_busy_driver(Config), + ?line process_flag(trap_exit, true), + + %% Start the waiters and make sure they have blocked. + ?line W1 = fun_spawn(fun quick_writer/0), + ?line W2 = fun_spawn(fun quick_writer/0), + ?line W3 = fun_spawn(fun quick_writer/0), + ?line W4 = fun_spawn(fun quick_writer/0), + ?line W5 = fun_spawn(fun quick_writer/0), + ?line test_server:sleep(500), % Make sure writers have blocked. + + %% Kill two of the processes. + exit(W1, kill), + receive {'EXIT', W1, killed} -> ok end, + exit(W3, kill), + receive {'EXIT', W3, killed} -> ok end, + + %% Unlock the port. The surviving processes should be become runnable. + ?line unlock_slave(), + ?line wait_for([W2, W4, W5]), + + ?line test_server:timetrap_cancel(Dog), + ok. + +quick_writer() -> + {Owner, Port} = get_slave(), + Port ! {Owner, {command, "port to busy"}}, + Port ! {Owner, {command, "lock me"}}, + ok. + +hard_busy_driver(Config) when is_list(Config) -> + hs_test(Config, true). + +soft_busy_driver(Config) when is_list(Config) -> + hs_test(Config, false). + +hs_test(Config, HardBusy) when is_list(Config) -> + ?line Me = self(), + ?line DrvName = case HardBusy of + true -> 'hard_busy_drv'; + false -> 'soft_busy_drv' + end, + ?line erl_ddll:start(), + ?line Path = ?config(data_dir, Config), + case erl_ddll:load_driver(Path, DrvName) of + ok -> ok; + {error, Error} -> + io:format("~s\n", [erl_ddll:format_error(Error)]), + ?line ?t:fail() + end, + + ?line Port = open_port({spawn, DrvName}, []), + + NotSuspended = fun (Proc) -> + chk_not_value({status,suspended}, + process_info(Proc, status)) + end, + NotBusyEnd = fun (Proc, Res, Time) -> + receive + {Port, caller, Proc} -> ok + after + 500 -> exit(missing_caller_message) + end, + chk_value({return, true}, Res), + chk_range(0, Time, 100) + end, + ForceEnd = fun (Proc, Res, Time) -> + case HardBusy of + false -> + NotBusyEnd(Proc, Res, Time); + true -> + chk_value({error, notsup}, Res), + chk_range(0, Time, 100), + receive + Msg -> exit({unexpected_msg, Msg}) + after + 500 -> ok + end + end + end, + BadArg = fun (_Proc, Res, Time) -> + chk_value({error, badarg}, Res), + chk_range(0, Time, 100) + end, + + %% Not busy + + %% Not busy; nosuspend option + ?line hs_busy_pcmd(Port, [nosuspend], NotSuspended, NotBusyEnd), + + %% Not busy; force option + ?line hs_busy_pcmd(Port, [force], NotSuspended, ForceEnd), + + %% Not busy; force and nosuspend option + ?line hs_busy_pcmd(Port, [force, nosuspend], NotSuspended, ForceEnd), + + %% Not busy; no option + ?line hs_busy_pcmd(Port, [], NotSuspended, NotBusyEnd), + + %% Not busy; bad option + ?line hs_busy_pcmd(Port, [bad_option], NotSuspended, BadArg), + + + %% Make busy + ?line erlang:port_control(Port, $B, []), + + + %% Busy; nosuspend option + ?line hs_busy_pcmd(Port, [nosuspend], NotSuspended, + fun (_Proc, Res, Time) -> + chk_value({return, false}, Res), + chk_range(0, Time, 100), + receive + Msg -> exit({unexpected_msg, Msg}) + after + 500 -> ok + end + end), + + %% Busy; force option + ?line hs_busy_pcmd(Port, [force], NotSuspended, ForceEnd), + + %% Busy; force and nosuspend option + ?line hs_busy_pcmd(Port, [force, nosuspend], NotSuspended, ForceEnd), + + %% Busy; bad option + ?line hs_busy_pcmd(Port, [bad_option], NotSuspended, BadArg), + + %% no option on busy port + ?line hs_busy_pcmd(Port, [], + fun (Proc) -> + receive after 1000 -> ok end, + chk_value({status,suspended}, + process_info(Proc, status)), + + %% Make not busy + erlang:port_control(Port, $N, []) + end, + fun (_Proc, Res, Time) -> + chk_value({return, true}, Res), + chk_range(1000, Time, 2000) + end), + + ?line true = erlang:port_close(Port), + ?line ok = erl_ddll:unload_driver(DrvName), + ?line ok = erl_ddll:stop(), + ?line ok. + +hs_busy_pcmd(Prt, Opts, StartFun, EndFun) -> + Tester = self(), + P = spawn_link(fun () -> + erlang:yield(), + Tester ! {self(), doing_port_command}, + Start = os:timestamp(), + Res = try {return, + erlang:port_command(Prt, [], Opts)} + catch Exception:Error -> {Exception, Error} + end, + End = os:timestamp(), + Time = round(timer:now_diff(End, Start)/1000), + Tester ! {self(), port_command_result, Res, Time} + end), + receive + {P, doing_port_command} -> + ok + end, + StartFun(P), + receive + {P, port_command_result, Res, Time} -> + EndFun(P, Res, Time) + end. + +%%% Utilities. + +chk_range(Min, Val, Max) when Min =< Val, Val =< Max -> + ok; +chk_range(Min, Val, Max) -> + exit({bad_range, Min, Val, Max}). + +chk_value(Exp, Exp) -> + ok; +chk_value(Exp, Val) -> + exit({unexpected_value, Val, expected, Exp}). + +chk_not_value(NotExp, NotExp) -> + exit({unexpected_not_value, NotExp}); +chk_not_value(_, _) -> + ok. + +wait_for([]) -> + ok; +wait_for(Pids) -> + io:format("Waiting for ~p", [Pids]), + receive + {'EXIT', Pid, normal} -> + wait_for(lists:delete(Pid, Pids)); + Other -> + test_server:fail({bad_exit, Other}) + end. + +fun_spawn(Fun) -> + fun_spawn(Fun, []). + +fun_spawn(Fun, Args) -> + spawn_link(erlang, apply, [Fun, Args]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% These routines provide a port which will become busy when the +%% the first message is sent to it. The unlock_slave/0 function can +%% be called (from another process) to make the port non-busy. +%% +%% Typical usage: +%% +%% start_busy_driver(Config) Load driver; start server. +%% +%% P r o c e s s O n e +%% {Owner, Port} = get_slave() O Obtain port and its owner. +%% Port ! {Owner, {command, List}} Send to port (will not block +%% but port will become busy). +%% Port ! {Owner, {command, List}} Will block the process. +%% +%% P r o c e s s T w o +%% unlock_slave() Set port to non-busy. Process One +%% will continue executing. Further +%% writes to the port will not block. +%% +%% Any process can call busy_drv:lock() to lock the port again. +%% +%% Note: This module must be used in an installed test suite (outside of +%% clearcase). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +load_busy_driver(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line erl_ddll:start(), + case erl_ddll:load_driver(DataDir, "busy_drv") of + ok -> ok; + {error, Error} -> + io:format("~s\n", [erl_ddll:format_error(Error)]), + ?line ?t:fail() + end. + +%%% Interface functions. + +start_busy_driver(Config) when is_list(Config) -> + ?line Pid = spawn_link(?MODULE, init, [Config, self()]), + ?line receive + {Pid, started} -> + ok; + Other -> + test_server:fail({unexpected_message, Other}) + end. + +unlock_slave() -> + command(unlock). + +get_slave() -> + ?line command(get_slave). + +%% Internal functions. + +command(Msg) -> + ?line whereis(busy_drv_server) ! {self(), Msg}, + ?line receive + {busy_drv_reply, Reply} -> + Reply + end. + +%%% Server. + +init(Config, ReplyTo) -> + register(busy_drv_server, self()), + load_busy_driver(Config), + Driver = "busy_drv", + Master = open_port({spawn, Driver++" master"}, []), + Slave = open_port({spawn, Driver++" slave"}, []), + ReplyTo ! {self(), started}, + loop(Master, Slave). + +loop(Master, Slave) -> + receive + {Pid, get_master} -> + Pid ! {busy_drv_reply, Master}, + loop(Master, Slave); + {Pid, get_slave} -> + Pid ! {busy_drv_reply, {self(), Slave}}, + loop(Master, Slave); + {Pid, unlock} -> + Master ! {self(), {command, "u"}}, + Pid ! {busy_drv_reply, ok}, + loop(Master, Slave); + {Pid, lock} -> + Master ! {self(), {command, "l"}}, + Pid ! {busy_drv_reply, ok}, + loop(Master, Slave); + {Pid, {port_command,Data}} -> + erlang:port_command(Slave, Data), + Pid ! {busy_drv_reply, ok}, + loop(Master, Slave); + {Pid, stop} -> + Pid ! {busy_drv_reply, ok} + end. diff --git a/erts/emulator/test/busy_port_SUITE_data/Makefile.src b/erts/emulator/test/busy_port_SUITE_data/Makefile.src new file mode 100644 index 0000000000..664909db71 --- /dev/null +++ b/erts/emulator/test/busy_port_SUITE_data/Makefile.src @@ -0,0 +1,25 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1997-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +all: busy_drv@dll@ hard_busy_drv@dll@ soft_busy_drv@dll@ + +@SHLIB_RULES@ + +hard_busy_drv@obj@: hard_busy_drv.c hs_busy_drv.c +soft_busy_drv@obj@: soft_busy_drv.c hs_busy_drv.c diff --git a/erts/emulator/test/busy_port_SUITE_data/busy_drv.c b/erts/emulator/test/busy_port_SUITE_data/busy_drv.c new file mode 100644 index 0000000000..1273d610ba --- /dev/null +++ b/erts/emulator/test/busy_port_SUITE_data/busy_drv.c @@ -0,0 +1,97 @@ +/* + * Purpose: Provides a driver whose busy state can be controlled from Erlang. + * Author: Bjorn Gustavsson + */ + +#include "erl_driver.h" +#include <stdio.h> +#include <string.h> + +#define NO 0 +#define YES 1 + +static ErlDrvData busy_start(ErlDrvPort, char*); +static void busy_stop(ErlDrvData), busy_from_erlang(ErlDrvData, char*, int); + +ErlDrvEntry busy_driver_entry = +{ + NULL, + busy_start, + busy_stop, + busy_from_erlang, + NULL, + NULL, + "busy_drv", + NULL, + NULL +}; + +static ErlDrvPort master_port; +static ErlDrvPort slave_port; +static int next_slave_state; + +DRIVER_INIT(busy_drv) +{ + master_port = (ErlDrvPort)-1; + slave_port = (ErlDrvPort)-1; + return &busy_driver_entry; +} + +static ErlDrvData busy_start(ErlDrvPort port, char* buf) +{ + char *s; + int slave = YES; + + s = strchr(buf, ' '); + if (s && s[1] == 'm') { + /* This is the master port */ + if (master_port != (ErlDrvPort)-1) + return ERL_DRV_ERROR_GENERAL; /* Already open */ + if (slave_port != (ErlDrvPort)-1) { + return ERL_DRV_ERROR_GENERAL; + } + master_port = port; + next_slave_state = 1; + } else { + if (slave_port != (ErlDrvPort)-1) + return ERL_DRV_ERROR_GENERAL; /* Already open */ + if (master_port == (ErlDrvPort)-1) { + return ERL_DRV_ERROR_GENERAL; + } + slave_port = port; + } + return (ErlDrvData)port; +} + +static void busy_stop(ErlDrvData port) +{ + if ((ErlDrvPort)port == master_port) { + master_port = (ErlDrvPort)-1; + } else if ((ErlDrvPort)port == slave_port) { + slave_port = (ErlDrvPort)-1; + } +} + +static void +busy_from_erlang(ErlDrvData port, char* buf, int count) +{ + if ((ErlDrvPort)port == slave_port) { + set_busy_port(slave_port, next_slave_state); + next_slave_state = 0; + return; + } + + if (slave_port == (ErlDrvPort)-1 || count < 1) { + driver_failure((ErlDrvPort)port, -1); + return; + } + + switch (buf[0]) { + case 'l': /* Lock port (set to busy) */ + set_busy_port(slave_port, 1); + break; + case 'u': /* Unlock port (not busy) */ + set_busy_port(slave_port, 0); + break; + } +} diff --git a/erts/emulator/test/busy_port_SUITE_data/hard_busy_drv.c b/erts/emulator/test/busy_port_SUITE_data/hard_busy_drv.c new file mode 100644 index 0000000000..52c41f8ca5 --- /dev/null +++ b/erts/emulator/test/busy_port_SUITE_data/hard_busy_drv.c @@ -0,0 +1,23 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ +#define ERTS_TEST_BUSY_DRV_NAME "hard_busy_drv" +#define ERTS_TEST_BUSY_DRV_FLAGS \ + ERL_DRV_FLAG_USE_PORT_LOCKING + +#include "hs_busy_drv.c" diff --git a/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c b/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c new file mode 100644 index 0000000000..35919da2d0 --- /dev/null +++ b/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c @@ -0,0 +1,94 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#include <errno.h> +#include "erl_driver.h" + +ErlDrvData start(ErlDrvPort port, char *command); +void output(ErlDrvData drv_data, char *buf, int len); +int control(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen); + +static ErlDrvEntry busy_drv_entry = { + NULL /* init */, + start, + NULL /* stop */, + output, + NULL /* ready_input */, + NULL /* ready_output */, + ERTS_TEST_BUSY_DRV_NAME, + NULL /* finish */, + NULL /* handle */, + control, + NULL /* timeout */, + NULL /* outputv */, + NULL /* ready_async */, + NULL /* flush */, + NULL /* call */, + NULL /* event */, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + ERTS_TEST_BUSY_DRV_FLAGS, + NULL /* handle2 */, + NULL /* handle_monitor */, + NULL /* stop_select */ +}; + +DRIVER_INIT(busy_drv) +{ + return &busy_drv_entry; +} + +ErlDrvData start(ErlDrvPort port, char *command) +{ + return (ErlDrvData) port; +} + +void output(ErlDrvData drv_data, char *buf, int len) +{ + int res; + ErlDrvPort port = (ErlDrvPort) drv_data; + ErlDrvTermData msg[] = { + ERL_DRV_PORT, driver_mk_port(port), + ERL_DRV_ATOM, driver_mk_atom("caller"), + ERL_DRV_PID, driver_caller(port), + ERL_DRV_TUPLE, (ErlDrvTermData) 3 + }; + res = driver_output_term(port, msg, sizeof(msg)/sizeof(ErlDrvTermData)); + if (res <= 0) + driver_failure_atom(port, "driver_output_term failed"); +} + +int control(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen) +{ + switch (command) { + case 'B': /* busy */ + set_busy_port((ErlDrvPort) drv_data, 1); + break; + case 'N': /* not busy */ + set_busy_port((ErlDrvPort) drv_data, 0); + break; + default: + driver_failure_posix((ErlDrvPort) drv_data, EINVAL); + break; + } + return 0; +} diff --git a/erts/emulator/test/busy_port_SUITE_data/soft_busy_drv.c b/erts/emulator/test/busy_port_SUITE_data/soft_busy_drv.c new file mode 100644 index 0000000000..30bcd86d1d --- /dev/null +++ b/erts/emulator/test/busy_port_SUITE_data/soft_busy_drv.c @@ -0,0 +1,23 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ +#define ERTS_TEST_BUSY_DRV_NAME "soft_busy_drv" +#define ERTS_TEST_BUSY_DRV_FLAGS \ + (ERL_DRV_FLAG_USE_PORT_LOCKING|ERL_DRV_FLAG_SOFT_BUSY) + +#include "hs_busy_drv.c" diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl new file mode 100644 index 0000000000..e0528955b0 --- /dev/null +++ b/erts/emulator/test/call_trace_SUITE.erl @@ -0,0 +1,1240 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +%%% Purpose : Tests the new call_trace BIF. + +-module(call_trace_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + hipe/1,process_specs/1,basic/1,flags/1,errors/1,pam/1,change_pam/1, + return_trace/1,exception_trace/1,on_load/1,deep_exception/1, + exception_nocatch/1,bit_syntax/1]). + +%% Helper functions. + +-export([bar/0,foo/0,foo/1,foo/2,expect/1,worker_foo/1,pam_foo/2,nasty/0, + id/1,deep/3,deep_1/3,deep_2/2,deep_3/2,deep_4/1,deep_5/1, + bs_sum_a/2,bs_sum_b/2]). + +%% Debug +-export([abbr/1,abbr/2]). + + +-include("test_server.hrl"). + +-define(P, 20). + +all(suite) -> + Common = [errors,on_load], + NotHipe = [process_specs,basic,flags,pam,change_pam,return_trace, + exception_trace,deep_exception,exception_nocatch,bit_syntax], + Hipe = [hipe], + case test_server:is_native(?MODULE) of + true -> Hipe ++ Common; + false -> NotHipe ++ Common + end. + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog = ?t:timetrap(?t:seconds(30)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +hipe(Config) when is_list(Config) -> + ?line 0 = erlang:trace_pattern({?MODULE,worker_foo,1}, true), + ?line 0 = erlang:trace_pattern({?MODULE,worker_foo,1}, true, [local]), + ?line AllFuncs = erlang:trace_pattern({'_','_','_'}, true), + + %% Make sure that a traced, exported function can still be found. + ?line true = erlang:function_exported(error_handler, undefined_function, 3), + ?line AllFuncs = erlang:trace_pattern({'_','_','_'}, false), + ok. + +process_specs(doc) -> + "Tests 'all', 'new', and 'existing' for specifying processes."; +process_specs(suite) -> []; +process_specs(Config) when is_list(Config) -> + ?line Tracer = start_tracer(), + ?line {flags,[call]} = trace_info(self(), flags), + ?line {tracer,Tracer} = trace_info(self(), tracer), + ?line trace_func({?MODULE,worker_foo,1}, []), + + %% Test the 'new' flag. + + ?line {Work1A,Work1B} = start_and_trace(new, [1,2,3], A1B={3,2,1}), + {flags,[]} = trace_info(Work1A, flags), + {tracer,[]} = trace_info(Work1A, tracer), + {tracer,Tracer} = trace_info(Work1B, tracer), + {flags,[call]} = trace_info(Work1B, flags), + ?line expect({trace,Work1B,call,{?MODULE,worker_foo,[A1B]}}), + ?line unlink(Work1B), + ?line Mref = erlang:monitor(process, Work1B), + ?line exit(Work1B, kill), + receive + {'DOWN',Mref,_,_,_} -> ok + end, + ?line undefined = trace_info(Work1B, flags), + ?line {flags,[]} = trace_info(new, flags), + ?line {tracer,[]} = trace_info(new, tracer), + + %% Test the 'existing' flag. + ?line {Work2A,_Work2B} = start_and_trace(existing, A2A=[5,6,7], [7,6,5]), + ?line expect({trace,Work2A,call,{?MODULE,worker_foo,[A2A]}}), + + %% Test the 'all' flag. + ?line {Work3A,Work3B} = start_and_trace(all, A3A=[12,13], A3B=[13,12]), + ?line expect({trace,Work3A,call,{?MODULE,worker_foo,[A3A]}}), + ?line expect({trace,Work3B,call,{?MODULE,worker_foo,[A3B]}}), + + ok. + +start_and_trace(Flag, A1, A2) -> + W1 = start_worker(), + trace_pid(Flag, true, [call]), + W2 = start_worker(), + call_worker(W1, A1), + call_worker(W2, A2), + case Flag of + new -> + {flags,[call]} = trace_info(new, flags), + {tracer,_} = trace_info(new, tracer); + _Other -> + ok + end, + trace_pid(Flag, false, [call]), + {W1,W2}. + +start_worker() -> + ?line spawn(fun worker_loop/0). + +call_worker(Pid, Arg) -> + Pid ! {self(),{call,Arg}}, + receive + {result,Res} -> Res + after 5000 -> + ?line ?t:fail(no_answer_from_worker) + end. + +worker_loop() -> + receive + {From,{call,Arg}} -> + From ! {result,?MODULE:worker_foo(Arg)}, + worker_loop(); + Other -> + exit({unexpected_message,Other}) + end. + +worker_foo(_Arg) -> + ok. + +basic(doc) -> + "Basic test of the call tracing (we trace one process)."; +basic(suite) -> []; +basic(Config) when is_list(Config) -> + ?line start_tracer(), + ?line trace_info(self(), flags), + ?line trace_info(self(), tracer), + ?line 0 = trace_func({?MODULE,no_such_function,0}, []), + ?line {traced,undefined} = + trace_info({?MODULE,no_such_function,0}, traced), + ?line {match_spec, undefined} = + trace_info({?MODULE,no_such_function,0}, match_spec), + + %% Trace some functions... + + ?line trace_func({lists,'_','_'}, []), + ?line 3 = trace_func({?MODULE,foo,'_'}, true), + ?line 1 = trace_func({?MODULE,bar,0}, true), + ?line {traced,global} = trace_info({?MODULE,bar,0}, traced), + ?line 1 = trace_func({erlang,list_to_integer,1}, true), + ?line {traced,global} = trace_info({erlang,list_to_integer,1}, traced), + + %% ... and call them... + + ?line AList = [x,y,z], + ?line true = lists:member(y, AList), + ?line foo0 = ?MODULE:foo(), + ?line 4 = ?MODULE:foo(3), + ?line 11 = ?MODULE:foo(7, 4), + ?line ok = ?MODULE:bar(), + ?line 42 = list_to_integer(non_literal("42")), + + %% ... make sure the we got trace messages (but not for ?MODULE:expect/1). + + ?line Self = self(), + ?line ?MODULE:expect({trace,Self,call,{lists,member,[y,AList]}}), + ?line ?MODULE:expect({trace,Self,call,{?MODULE,foo,[]}}), + ?line ?MODULE:expect({trace,Self,call,{?MODULE,foo,[3]}}), + ?line ?MODULE:expect({trace,Self,call,{?MODULE,foo,[7,4]}}), + ?line ?MODULE:expect({trace,Self,call,{?MODULE,bar,[]}}), + ?line ?MODULE:expect({trace,Self,call,{erlang,list_to_integer,["42"]}}), + + %% Turn off trace for this module and call functions... + + ?line trace_func({?MODULE,'_','_'}, false), + ?line {traced,false} = trace_info({?MODULE,bar,0}, traced), + ?line foo0 = ?MODULE:foo(), + ?line 4 = ?MODULE:foo(3), + ?line 11 = ?MODULE:foo(7, 4), + ?line ok = ?MODULE:bar(), + ?line [1,2,3,4,5,6,7,8,9,10] = lists:seq(1, 10), + ?line 777 = list_to_integer(non_literal("777")), + + %% ... turn on all trace messages... + + ?line trace_func({'_','_','_'}, false), + ?line [b,a] = lists:reverse([a,b]), + + %% Read out the remaing trace messages. + + ?line ?MODULE:expect({trace,Self,call,{lists,seq,[1,10]}}), + ?line ?MODULE:expect({trace,Self,call,{erlang,list_to_integer,["777"]}}), + receive + Any -> + ?line ?t:fail({unexpected_message,Any}) + after 1 -> + ok + end, + + %% Turn on and then off tracing on all external functions. + %% This might cause the emulator to crasch later if it doesn't + %% restore all export entries properly. + + ?line AllFuncs = trace_func({'_','_','_'}, true), + io:format("AllFuncs = ~p", [AllFuncs]), + %% Make sure that a traced, exported function can still be found. + ?line true = erlang:function_exported(error_handler, undefined_function, 3), + ?line AllFuncs = trace_func({'_','_','_'}, false), + ?line erlang:trace_delivered(all), + receive + {trace_delivered,_,_} -> ok + end, + c:flush(), % Print the traces messages. + c:flush(), % Print the traces messages. + + ?line {traced,false} = trace_info({erlang,list_to_integer,1}, traced), + + ok. + +non_literal(X) -> X. + +bar() -> + ok. + +foo() -> foo0. +foo(X) -> X+1. +foo(X, Y) -> X+Y. + +flags(doc) -> "Test flags (arity, timestamp) for call_trace/3. " + "Also, test the '{tracer,Pid}' option."; +flags(Config) when is_list(Config) -> + ?line Tracer = start_tracer_loop(), + ?line trace_pid(self(), true, [call,{tracer,Tracer}]), + + %% Trace some functions... + + ?line trace_func({filename,'_','_'}, true), + + %% ... and call them... + + ?line Self = self(), + ?line filename:absname("nisse"), + ?line ?MODULE:expect({trace,Self,call,{filename,absname,["nisse"]}}), + ?line trace_pid(Self, true, [call,arity]), + ?line filename:absname("kalle"), + ?line filename:absname("kalle", "/root"), + ?line ?MODULE:expect({trace,Self,call,{filename,absname,1}}), + ?line ?MODULE:expect({trace,Self,call,{filename,absname,2}}), + ?line trace_info(Self, flags), + + %% Timestamp + arity. + + flag_test(fun() -> + ?line trace_pid(Self, true, [timestamp]), + ?line "dum" = filename:basename("/abcd/dum"), + ?line Ts = expect({trace_ts,Self,call,{filename,basename,1},ts}), + ?line trace_info(Self, flags), + Ts + end), + + %% Timestamp. + + ?line AnArg = "/abcd/hejsan", + flag_test(fun() -> + ?line trace_pid(Self, false, [arity]), + ?line "hejsan" = filename:basename(AnArg), + ?line Ts = expect({trace_ts,Self,call, + {filename,basename,[AnArg]},ts}), + ?line trace_info(Self, flags), + Ts + end), + + %% All flags turned off. + + ?line trace_pid(Self, false, [timestamp]), + ?line AnotherArg = filename:join(AnArg, "hoppsan"), + ?line "hoppsan" = filename:basename(AnotherArg), + ?line expect({trace,Self,call,{filename,join,[AnArg,"hoppsan"]}}), + ?line expect({trace,Self,call,{filename,basename,[AnotherArg]}}), + ?line trace_info(Self, flags), + + ok. + +flag_test(Test) -> + Now = now(), + Ts = Test(), + case timer:now_diff(Ts, Now) of + Time when Time < 5*1000000 -> + %% Reasonable short time. + ok; + _Diff -> + %% Too large difference. + io:format("Now = ~p\n", [Now]), + io:format("Ts = ~p\n", [Ts]), + ?line ?t:fail() + end, + flag_test_cpu_timestamp(Test). + +flag_test_cpu_timestamp(Test) -> + try erlang:trace(all, true, [cpu_timestamp]) of + _ -> + io:format("CPU timestamps"), + Ts = Test(), + erlang:trace(all, false, [cpu_timestamp]), + Origin = {0,0,0}, + Hour = 3600*1000000, + case timer:now_diff(Ts, Origin) of + Diff when Diff < 4*Hour -> + %% In the worst case, CPU timestamps count from when this + %% Erlang emulator was started. The above test is a conservative + %% test that all CPU timestamps should pass. + ok; + _Time -> + io:format("Strange CPU timestamp: ~p", [Ts]), + ?line ?t:fail() + end, + io:format("Turned off CPU timestamps") + catch + error:badarg -> ok + end. + +errors(doc) -> "Test bad arguments for trace/3 and trace_pattern/3."; +errors(suite) -> []; +errors(Config) when is_list(Config) -> + ?line expect_badarg_pid(aaa, true, []), + ?line expect_badarg_pid({pid,dum}, false, []), + ?line expect_badarg_func({'_','_',1}, []), + ?line expect_badarg_func({'_',gosh,1}, []), + ?line expect_badarg_func({xxx,'_',2}, []), + ?line expect_badarg_func({xxx,yyy,b}, glurp), + ok. + +expect_badarg_pid(What, How, Flags) -> + case catch erlang:trace(What, How, Flags) of + {'EXIT',{badarg,Where}} -> + io:format("trace(~p, ~p, ~p) ->\n {'EXIT',{badarg,~p}}", + [What,How,Flags,Where]), + ok; + Other -> + io:format("trace(~p, ~p, ~p) -> ~p", + [What,How,Flags,Other]), + ?t:fail({unexpected,Other}) + end. + +expect_badarg_func(MFA, Pattern) -> + case catch erlang:trace_pattern(MFA, Pattern) of + {'EXIT',{badarg,Where}} -> + io:format("trace_pattern(~p, ~p) ->\n {'EXIT',{badarg,~p}}", + [MFA,Pattern,Where]), + ok; + Other -> + io:format("trace_pattern(~p, ~p) -> ~p", + [MFA, Pattern, Other]), + ?t:fail({unexpected,Other}) + end. + +pam(doc) -> "Basic test of PAM."; +pam(suite) -> []; +pam(Config) when is_list(Config) -> + ?line start_tracer(), + ?line Self = self(), + + %% Build the match program. + ?line Prog1 = {[{a,tuple},'$1'],[],[]}, + ?line Prog2 = {[{a,bigger,tuple},'$1'],[],[{message,'$1'}]}, + ?line MatchProg = [Prog1,Prog2], + ?line pam_trace(MatchProg), + + %% Do some calls. + ?line ?MODULE:pam_foo(not_a_tuple, [a,b]), + ?line ?MODULE:pam_foo({a,tuple}, [a,list]), + ?line ?MODULE:pam_foo([this,one,will,'not',match], dummy_arg), + ?line LongList = lists:seq(1,10), + ?line ?MODULE:pam_foo({a,bigger,tuple}, LongList), + + %% Check that we get the correct trace messages. + ?line expect({trace,Self,call,{?MODULE,pam_foo,[{a,tuple},[a,list]]}}), + ?line expect({trace,Self,call, + {?MODULE,pam_foo,[{a,bigger,tuple},LongList]}, + LongList}), + + ?line trace_func({?MODULE,pam_foo,'_'}, false), + ok. + +pam_trace(Prog) -> + 1 = trace_func({?MODULE,pam_foo,'_'}, Prog), + {match_spec,Prog} = trace_info({?MODULE,pam_foo,2}, match_spec), + ok. + +pam_foo(A, B) -> + {ok,A,B}. + + +change_pam(doc) -> "Test changing PAM programs for a function."; +change_pam(suite) -> []; +change_pam(Config) when is_list(Config) -> + ?line start_tracer(), + ?line Self = self(), + + %% Install the first match program. + %% Test using timestamp at the same time. + + ?line trace_pid(Self, true, [call,arity,timestamp]), + ?line Prog1 = [{['$1','$2'],[],[{message,'$1'}]}], + ?line change_pam_trace(Prog1), + ?line [x,y] = lists:append(id([x]), id([y])), + ?line {heap_size,_} = erlang:process_info(Self, heap_size), + ?line expect({trace_ts,Self,call,{lists,append,2},[x],ts}), + ?line expect({trace_ts,Self,call,{erlang,process_info,2},Self,ts}), + + %% Install a new PAM program. + + ?line Prog2 = [{['$1','$2'],[],[{message,'$2'}]}], + ?line change_pam_trace(Prog2), + ?line [xx,yy] = lists:append(id([xx]), id([yy])), + ?line {current_function,_} = erlang:process_info(Self, current_function), + ?line expect({trace_ts,Self,call,{lists,append,2},[yy],ts}), + ?line expect({trace_ts,Self,call,{erlang,process_info,2},current_function,ts}), + + ?line 1 = trace_func({lists,append,2}, false), + ?line 1 = trace_func({erlang,process_info,2}, false), + ?line {match_spec,false} = trace_info({lists,append,2}, match_spec), + ?line {match_spec,false} = trace_info({erlang,process_info,2}, match_spec), + + ok. + +change_pam_trace(Prog) -> + 1 = trace_func({lists,append,2}, Prog), + 1 = trace_func({erlang,process_info,2}, Prog), + {match_spec,Prog} = trace_info({lists,append,2}, match_spec), + {match_spec,Prog} = trace_info({erlang,process_info,2}, match_spec), + ok. + +return_trace(doc) -> "Test the new return trace."; +return_trace(suite) -> []; +return_trace(Config) when is_list(Config) -> + return_trace(). + +return_trace() -> + X = {save,me}, + ?line start_tracer(), + ?line Self = self(), + + %% Test call and return trace and timestamp. + + ?line trace_pid(Self, true, [call,timestamp]), + Stupid = {pointless,tuple}, + ?line Prog1 = [{['$1','$2'],[],[{return_trace},{message,{Stupid}}]}], + ?line 1 = trace_func({lists,append,2}, Prog1), + ?line 1 = trace_func({erlang,process_info,2}, Prog1), + ?line {match_spec,Prog1} = trace_info({lists,append,2}, match_spec), + ?line {match_spec,Prog1} = trace_info({erlang,process_info,2}, match_spec), + + ?line [x,y] = lists:append(id([x]), id([y])), + Current = {current_function,{?MODULE,return_trace,0}}, + ?line Current = erlang:process_info(Self, current_function), + ?line expect({trace_ts,Self,call,{lists,append,[[x],[y]]},Stupid,ts}), + ?line expect({trace_ts,Self,return_from,{lists,append,2},[x,y],ts}), + ?line expect({trace_ts,Self,call,{erlang,process_info,[Self,current_function]}, + Stupid,ts}), + ?line expect({trace_ts,Self,return_from,{erlang,process_info,2},Current,ts}), + + %% Try catch/exit. + + ?line 1 = trace_func({?MODULE,nasty,0}, [{[],[],[{return_trace},{message,false}]}]), + ?line {'EXIT',good_bye} = (catch ?MODULE:nasty()), + ?line 1 = trace_func({?MODULE,nasty,0}, false), + + %% Turn off trace. + + ?line 1 = trace_func({lists,append,2}, false), + ?line 1 = trace_func({erlang,process_info,2}, false), + ?line {match_spec,false} = trace_info({lists,append,2}, match_spec), + ?line {match_spec,false} = trace_info({erlang,process_info,2}, match_spec), + + %% No timestamp, no trace message for call. + + ?line trace_pid(Self, false, [timestamp]), + ?line Prog2 = [{['$1','$2'],[],[{return_trace},{message,false}]}, + {['$1'],[],[{return_trace},{message,false}]}], + ?line 1 = trace_func({lists,seq,2}, Prog2), + ?line 1 = trace_func({erlang,atom_to_list,1}, Prog2), + ?line {match_spec,Prog2} = trace_info({lists,seq,2}, match_spec), + ?line {match_spec,Prog2} = trace_info({erlang,atom_to_list,1}, match_spec), + + ?line lists:seq(2, 7), + ?line atom_to_list(non_literal(nisse)), + ?line expect({trace,Self,return_from,{lists,seq,2},[2,3,4,5,6,7]}), + ?line expect({trace,Self,return_from,{erlang,atom_to_list,1},"nisse"}), + + %% Turn off trace. + + ?line 1 = trace_func({lists,seq,2}, false), + ?line 1 = trace_func({erlang,atom_to_list,1}, false), + ?line {match_spec,false} = trace_info({lists,seq,2}, match_spec), + ?line {match_spec,false} = trace_info({erlang,atom_to_list,1}, match_spec), + + ?line {save,me} = X, + + ok. + +nasty() -> + exit(good_bye). + +exception_trace(doc) -> "Test the new exception trace."; +exception_trace(suite) -> []; +exception_trace(Config) when is_list(Config) -> + exception_trace(). + +exception_trace() -> + X = {save,me}, + ?line start_tracer(), + ?line Self = self(), + + %% Test call and return trace and timestamp. + + ?line trace_pid(Self, true, [call,timestamp]), + Stupid = {pointless,tuple}, + ?line Prog1 = [{['$1','$2'],[],[{exception_trace},{message,{Stupid}}]}], + ?line 1 = trace_func({lists,append,2}, Prog1), + ?line 1 = trace_func({erlang,process_info,2}, Prog1), + ?line {match_spec,Prog1} = trace_info({lists,append,2}, match_spec), + ?line {match_spec,Prog1} = + trace_info({erlang,process_info,2}, match_spec), + + ?line [x,y] = lists:append(id([x]), id([y])), + Current = {current_function,{?MODULE,exception_trace,0}}, + ?line Current = erlang:process_info(Self, current_function), + ?line expect({trace_ts,Self,call,{lists,append,[[x],[y]]},Stupid,ts}), + ?line expect({trace_ts,Self,return_from,{lists,append,2},[x,y],ts}), + ?line expect({trace_ts,Self,call,{erlang,process_info, + [Self,current_function]}, + Stupid,ts}), + ?line expect({trace_ts,Self,return_from, + {erlang,process_info,2},Current,ts}), + + %% Try catch/exit. + + ?line 1 = trace_func({?MODULE,nasty,0}, + [{[],[],[{exception_trace},{message,false}]}]), + ?line {'EXIT',good_bye} = (catch ?MODULE:nasty()), + ?line expect({trace_ts,Self,exception_from, + {?MODULE,nasty,0},{exit,good_bye},ts}), + ?line 1 = trace_func({?MODULE,nasty,0}, false), + + %% Turn off trace. + + ?line 1 = trace_func({lists,append,2}, false), + ?line 1 = trace_func({erlang,process_info,2}, false), + ?line {match_spec,false} = trace_info({lists,append,2}, match_spec), + ?line {match_spec,false} = + trace_info({erlang,process_info,2}, match_spec), + + %% No timestamp, no trace message for call. + + ?line trace_pid(Self, false, [timestamp]), + ?line Prog2 = [{['$1','$2'],[],[{exception_trace},{message,false}]}, + {['$1'],[],[{exception_trace},{message,false}]}], + ?line 1 = trace_func({lists,seq,2}, Prog2), + ?line 1 = trace_func({erlang,atom_to_list,1}, Prog2), + ?line {match_spec,Prog2} = trace_info({lists,seq,2}, match_spec), + ?line {match_spec,Prog2} = + trace_info({erlang,atom_to_list,1}, match_spec), + + ?line lists:seq(2, 7), + ?line atom_to_list(non_literal(nisse)), + ?line expect({trace,Self,return_from,{lists,seq,2},[2,3,4,5,6,7]}), + ?line expect({trace,Self,return_from,{erlang,atom_to_list,1},"nisse"}), + + %% Turn off trace. + + ?line 1 = trace_func({lists,seq,2}, false), + ?line 1 = trace_func({erlang,atom_to_list,1}, false), + ?line {match_spec,false} = trace_info({lists,seq,2}, match_spec), + ?line {match_spec,false} = + trace_info({erlang,atom_to_list,1}, match_spec), + + ?line expect(), + ?line {save,me} = X, + ok. + +on_load(doc) -> "Test the on_load argument for trace_pattern/3."; +on_load(suite) -> []; +on_load(Config) when is_list(Config) -> + ?line 0 = erlang:trace_pattern(on_load, []), + ?line {traced,global} = erlang:trace_info(on_load, traced), + ?line {match_spec,[]} = erlang:trace_info(on_load, match_spec), + + ?line 0 = erlang:trace_pattern(on_load, true, [local]), + ?line {traced,local} = erlang:trace_info(on_load, traced), + ?line {match_spec,[]} = erlang:trace_info(on_load, match_spec), + + ?line 0 = erlang:trace_pattern(on_load, false, [local]), + ?line {traced,false} = erlang:trace_info(on_load, traced), + ?line {match_spec,false} = erlang:trace_info(on_load, match_spec), + + ?line Pam1 = [{[],[],[{message,false}]}], + ?line 0 = erlang:trace_pattern(on_load, Pam1), + ?line {traced,global} = erlang:trace_info(on_load, traced), + ?line {match_spec,Pam1} = erlang:trace_info(on_load, match_spec), + + ?line 0 = erlang:trace_pattern(on_load, true, [local]), + ?line 0 = erlang:trace_pattern(on_load, false, [local]), + + ok. + + + +deep_exception(doc) -> "Test the new exception trace."; +deep_exception(suite) -> []; +deep_exception(Config) when is_list(Config) -> + deep_exception(). + +deep_exception() -> + ?line start_tracer(), + ?line Self = self(), + ?line N = 200000, + ?line LongImproperList = seq(1, N-1, N), + + Prog = [{'_',[],[{exception_trace}]}], +%% ?line 1 = trace_pid(Self, true, [call]), + ?line 1 = trace_func({?MODULE,deep,'_'}, Prog), + ?line 1 = trace_func({?MODULE,deep_1,'_'}, Prog), + ?line 1 = trace_func({?MODULE,deep_2,'_'}, Prog), + ?line 1 = trace_func({?MODULE,deep_3,'_'}, Prog), + ?line 1 = trace_func({?MODULE,deep_4,'_'}, Prog), + ?line 1 = trace_func({?MODULE,deep_5,'_'}, Prog), + ?line 1 = trace_func({?MODULE,id,'_'}, Prog), + ?line 1 = trace_func({erlang,'++','_'}, Prog), + ?line 1 = trace_func({erlang,exit,1}, Prog), + ?line 1 = trace_func({erlang,throw,1}, Prog), + ?line 2 = trace_func({erlang,error,'_'}, Prog), + ?line 1 = trace_func({lists,reverse,2}, Prog), + + ?line deep_exception(?LINE, exit, [paprika], 1, + [{trace,Self,call,{erlang,exit,[paprika]}}, + {trace,Self,exception_from,{erlang,exit,1}, + {exit,paprika}}], + exception_from, {exit,paprika}), + ?line deep_exception(?LINE, throw, [3.14], 2, + [{trace,Self,call,{erlang,throw,[3.14]}}, + {trace,Self,exception_from,{erlang,throw,1}, + {throw,3.14}}], + exception_from, {throw,3.14}), + ?line deep_exception(?LINE, error, [{paprika}], 3, + [{trace,Self,call,{erlang,error,[{paprika}]}}, + {trace,Self,exception_from,{erlang,error,1}, + {error,{paprika}}}], + exception_from, {error,{paprika}}), + ?line deep_exception(?LINE, error, ["{paprika}",[]], 3, + [{trace,Self,call,{erlang,error,["{paprika}",[]]}}, + {trace,Self,exception_from,{erlang,error,2}, + {error,"{paprika}"}}], + exception_from, {error,"{paprika}"}), + ?line deep_exception(?LINE, id, [broccoli], 4, [], + return_from, broccoli), + ?line deep_exception( + ?LINE, append, [1,2], 5, + [{trace,Self,call,{erlang,'++',[1,2]}}, + {trace,Self,exception_from,{erlang,'++',2},{error,badarg}}], + exception_from, {error,badarg}), + ?line deep_exception(?LINE, '=', [1,2], 6, [], + exception_from, {error,{badmatch,2}}), + %% + ?line io:format("== Subtest: ~w", [?LINE]), + ?line try lists:reverse(LongImproperList, []) of + R1 -> test_server:fail({returned,abbr(R1)}) + catch error:badarg -> ok + end, + ?line expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}}) + when is_list(L1), is_list(L2), S == Self -> + next; + ({trace,S,exception_from, + {lists,reverse,2},{error,badarg}}) + when S == Self -> + expected; + ('_') -> + {trace,Self,exception_from, + {lists,reverse,2},{error,badarg}}; + (_) -> + {unexpected, + {trace,Self,exception_from, + {lists,reverse,2},{error,badarg}}} + end), + ?line deep_exception(?LINE, deep_5, [1,2], 7, + [{trace,Self,call,{erlang,error,[undef]}}, + {trace,Self,exception_from,{erlang,error,1}, + {error,undef}}], + exception_from, {error,undef}), + ?line deep_exception(?LINE, deep_5, [undef], 8, + [{trace,Self,call,{?MODULE,deep_5,[undef]}}, + {trace,Self,exception_from,{?MODULE,deep_5,1}, + {error,function_clause}}], + exception_from, {error,function_clause}), + + %% Apply + %% + ?line deep_exception(?LINE, apply, [erlang,error,[[mo|rot]]], 1, + [{trace,Self,call,{erlang,error,[[mo|rot]]}}, + {trace,Self,exception_from,{erlang,error,1}, + {error,[mo|rot]}}], + exception_from, {error,[mo|rot]}), + ?line deep_exception(?LINE, apply, [erlang,error,[[mo|"rot"],[]]], 1, + [{trace,Self,call,{erlang,error,[[mo|"rot"],[]]}}, + {trace,Self,exception_from,{erlang,error,2}, + {error,[mo|"rot"]}}], + exception_from, {error,[mo|"rot"]}), + ?line Morot = make_ref(), + ?line deep_exception(?LINE, apply, [erlang,throw,[Morot]], 3, + [{trace,Self,call,{erlang,throw,[Morot]}}, + {trace,Self,exception_from,{erlang,throw,1}, + {throw,Morot}}], + exception_from, {throw,Morot}), + ?line deep_exception(?LINE, apply, [erlang,exit,[["morot"|Morot]]], 2, + [{trace,Self,call,{erlang,exit,[["morot"|Morot]]}}, + {trace,Self,exception_from,{erlang,exit,1}, + {exit,["morot"|Morot]}}], + exception_from, {exit,["morot"|Morot]}), + ?line deep_exception( + ?LINE, apply, [?MODULE,id,[spenat]], 4, + [{trace,Self,call,{?MODULE,id,[spenat]}}, + {trace,Self,return_from,{?MODULE,id,1},spenat}], + return_from, spenat), + ?line deep_exception( + ?LINE, apply, [erlang,'++',[1,2]], 5, + [{trace,Self,call,{erlang,'++',[1,2]}}, + {trace,Self,exception_from,{erlang,'++',2},{error,badarg}}], + exception_from, {error,badarg}), + ?line io:format("== Subtest: ~w", [?LINE]), + ?line try apply(lists, reverse, [LongImproperList, []]) of + R2 -> test_server:fail({returned,abbr(R2)}) + catch error:badarg -> ok + end, + ?line expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}}) + when is_list(L1), is_list(L2), S == Self -> + next; + ({trace,S,exception_from, + {lists,reverse,2},{error,badarg}}) + when S == Self -> + expected; + ('_') -> + {trace,Self,exception_from, + {lists,reverse,2},{error,badarg}}; + (_) -> + {unexpected, + {trace,Self,exception_from, + {lists,reverse,2},{error,badarg}}} + end), + ?line deep_exception(?LINE, apply, [?MODULE,deep_5,[1,2]], 7, + [{trace,Self,call,{erlang,error,[undef]}}, + {trace,Self,exception_from,{erlang,error,1}, + {error,undef}}], + exception_from, {error,undef}), + ?line deep_exception(?LINE, apply, [?MODULE,deep_5,[undef]], 8, + [{trace,Self,call,{?MODULE,deep_5,[undef]}}, + {trace,Self,exception_from,{?MODULE,deep_5,1}, + {error,function_clause}}], + exception_from, {error,function_clause}), + %% Apply of fun + %% + ?line deep_exception(?LINE, apply, + [fun () -> + erlang:error([{"palsternacka",3.14},17]) + end, []], 1, + [{trace,Self,call, + {erlang,error,[[{"palsternacka",3.14},17]]}}, + {trace,Self,exception_from,{erlang,error,1}, + {error,[{"palsternacka",3.14},17]}}], + exception_from, {error,[{"palsternacka",3.14},17]}), + ?line deep_exception(?LINE, apply, + [fun () -> + erlang:error(["palsternacka",17], []) + end, []], 1, + [{trace,Self,call, + {erlang,error,[["palsternacka",17],[]]}}, + {trace,Self,exception_from,{erlang,error,2}, + {error,["palsternacka",17]}}], + exception_from, {error,["palsternacka",17]}), + ?line deep_exception(?LINE, apply, + [fun () -> erlang:throw(Self) end, []], 2, + [{trace,Self,call,{erlang,throw,[Self]}}, + {trace,Self,exception_from,{erlang,throw,1}, + {throw,Self}}], + exception_from, {throw,Self}), + ?line deep_exception(?LINE, apply, + [fun () -> + erlang:exit({1,2,3,4,[5,palsternacka]}) + end, []], 3, + [{trace,Self,call, + {erlang,exit,[{1,2,3,4,[5,palsternacka]}]}}, + {trace,Self,exception_from,{erlang,exit,1}, + {exit,{1,2,3,4,[5,palsternacka]}}}], + exception_from, {exit,{1,2,3,4,[5,palsternacka]}}), + ?line deep_exception(?LINE, apply, + [fun () -> ?MODULE:id(bladsallad) end, []], 4, + [{trace,Self,call,{?MODULE,id,[bladsallad]}}, + {trace,Self,return_from,{?MODULE,id,1},bladsallad}], + return_from, bladsallad), + ?line deep_exception(?LINE, apply, + [fun (A, B) -> A ++ B end, [1,2]], 5, + [{trace,Self,call,{erlang,'++',[1,2]}}, + {trace,Self,exception_from, + {erlang,'++',2},{error,badarg}}], + exception_from, {error,badarg}), + ?line deep_exception(?LINE, apply, [fun (A, B) -> A = B end, [1,2]], 6, + [], + exception_from, {error,{badmatch,2}}), + ?line io:format("== Subtest: ~w", [?LINE]), + ?line try apply(fun() -> lists:reverse(LongImproperList, []) end, []) of + R3 -> test_server:fail({returned,abbr(R3)}) + catch error:badarg -> ok + end, + ?line expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}}) + when is_list(L1), is_list(L2), S == Self -> + next; + ({trace,S,exception_from, + {lists,reverse,2},{error,badarg}}) + when S == Self -> + expected; + ('_') -> + {trace,Self,exception_from, + {lists,reverse,2},{error,badarg}}; + (_) -> + {unexpected, + {trace,Self,exception_from, + {lists,reverse,2},{error,badarg}}} + end), + ?line deep_exception(?LINE, apply, + [fun () -> ?MODULE:deep_5(1,2) end, []], 7, + [{trace,Self,call,{erlang,error,[undef]}}, + {trace,Self,exception_from,{erlang,error,1}, + {error,undef}}], + exception_from, {error,undef}), + ?line deep_exception(?LINE, apply, + [fun () -> ?MODULE:deep_5(undef) end, []], 8, + [{trace,Self,call,{?MODULE,deep_5,[undef]}}, + {trace,Self,exception_from,{?MODULE,deep_5,1}, + {error,function_clause}}], + exception_from, {error,function_clause}), + + ?line trace_func({?MODULE,'_','_'}, false), + ?line trace_func({erlang,'_','_'}, false), + ?line trace_func({lists,'_','_'}, false), + ?line expect(), + ?line ok. + + +deep_exception(Line, B, Q, N, Extra, Tag, R) -> + ?line Self = self(), + ?line io:format("== Subtest: ~w", [Line]), + ?line Result = ?MODULE:deep(N, B, Q), + ?line Result = deep_expect(Self, B, Q, N, Extra, Tag, R). + +deep_expect(Self, B, Q, N, Extra, Tag, R) -> + ?line expect({trace,Self,call,{?MODULE,deep,[N,B,Q]}}), + ?line Result = deep_expect_N(Self, B, Q, N, Extra, Tag, R), + ?line expect({trace,Self,return_from,{?MODULE,deep,3},Result}), + ?line Result. + +deep_expect_N(Self, B, Q, N, Extra, Tag, R) -> + deep_expect_N(Self, B, Q, N, Extra, Tag, R, N). + +deep_expect_N(Self, B, Q, N, Extra, Tag, R, J) when J > 0 -> + ?line expect({trace,Self,call,{?MODULE,deep_1,[J,B,Q]}}), + ?line deep_expect_N(Self, B, Q, N, Extra, Tag, R, J-1); +deep_expect_N(Self, B, Q, N, Extra, Tag, R, 0) -> + ?line expect({trace,Self,call,{?MODULE,deep_2,[B,Q]}}), + ?line expect({trace,Self,call,{?MODULE,deep_3,[B,Q]}}), + ?line expect({trace,Self,return_from,{?MODULE,deep_3,2},{B,Q}}), + ?line expect({trace,Self,call,{?MODULE,deep_4,[{B,Q}]}}), + ?line expect({trace,Self,call,{?MODULE,id,[{B,Q}]}}), + ?line expect({trace,Self,return_from,{?MODULE,id,1},{B,Q}}), + ?line deep_expect_Extra(Self, N, Extra, Tag, R), + ?line expect({trace,Self,Tag,{?MODULE,deep_4,1},R}), + ?line expect({trace,Self,Tag,{?MODULE,deep_2,2},R}), + ?line deep_expect_N(Self, N, Tag, R). + +deep_expect_Extra(Self, N, [E|Es], Tag, R) -> + ?line expect(E), + ?line deep_expect_Extra(Self, N, Es, Tag, R); +deep_expect_Extra(_Self, _N, [], _Tag, _R) -> + ?line ok. + +deep_expect_N(Self, N, Tag, R) when N > 0 -> + ?line expect({trace,Self,Tag,{?MODULE,deep_1,3},R}), + ?line deep_expect_N(Self, N-1, Tag, R); +deep_expect_N(_Self, 0, return_from, R) -> + ?line {value,R}; +deep_expect_N(_Self, 0, exception_from, R) -> + ?line R. + + + +exception_nocatch(doc) -> "Test the new exception trace."; +exception_nocatch(suite) -> []; +exception_nocatch(Config) when is_list(Config) -> + exception_nocatch(). + +exception_nocatch() -> + Prog = [{'_',[],[{exception_trace}]}], + ?line 1 = erlang:trace_pattern({?MODULE,deep_1,'_'}, Prog), + ?line 1 = erlang:trace_pattern({?MODULE,deep_2,'_'}, Prog), + ?line 1 = erlang:trace_pattern({?MODULE,deep_3,'_'}, Prog), + ?line 1 = erlang:trace_pattern({?MODULE,deep_4,'_'}, Prog), + ?line 1 = erlang:trace_pattern({?MODULE,deep_5,'_'}, Prog), + ?line 1 = erlang:trace_pattern({?MODULE,id,'_'}, Prog), + ?line 1 = erlang:trace_pattern({erlang,exit,1}, Prog), + ?line 1 = erlang:trace_pattern({erlang,throw,1}, Prog), + ?line 2 = erlang:trace_pattern({erlang,error,'_'}, Prog), + ?line Q1 = {make_ref(),Prog}, + ?line T1 = + exception_nocatch(?LINE, exit, [Q1], 3, + [{trace,t1,call,{erlang,exit,[Q1]}}, + {trace,t1,exception_from,{erlang,exit,1}, + {exit,Q1}}], + exception_from, {exit,Q1}), + ?line expect({trace,T1,exit,Q1}), + ?line Q2 = {cake,14.125}, + ?line T2 = + exception_nocatch(?LINE, throw, [Q2], 2, + [{trace,t2,call,{erlang,throw,[Q2]}}, + {trace,t2,exception_from,{erlang,throw,1}, + {error,{nocatch,Q2}}}], + exception_from, {error,{nocatch,Q2}}), + ?line expect({trace,T2,exit,{{nocatch,Q2},[{erlang,throw,[Q2]}, + {?MODULE,deep_4,1}]}}), + ?line Q3 = {dump,[dump,{dump}]}, + ?line T3 = + exception_nocatch(?LINE, error, [Q3], 4, + [{trace,t3,call,{erlang,error,[Q3]}}, + {trace,t3,exception_from,{erlang,error,1}, + {error,Q3}}], + exception_from, {error,Q3}), + ?line expect({trace,T3,exit,{Q3,[{erlang,error,[Q3]}, + {?MODULE,deep_4,1}]}}), + ?line T4 = + exception_nocatch(?LINE, '=', [17,4711], 5, [], + exception_from, {error,{badmatch,4711}}), + ?line expect({trace,T4,exit,{{badmatch,4711},[{?MODULE,deep_4,1}]}}), + %% + ?line erlang:trace_pattern({?MODULE,'_','_'}, false), + ?line erlang:trace_pattern({erlang,'_','_'}, false), + ?line expect(), + ?line ok. + +exception_nocatch(Line, B, Q, N, Extra, Tag, R) -> + ?line io:format("== Subtest: ~w", [Line]), + ?line Go = make_ref(), + ?line Tracee = + spawn(fun () -> + receive + Go -> + deep_1(N, B, Q) + end + end), + ?line 1 = erlang:trace(Tracee, true, [call,return_to,procs]), + ?line Tracee ! Go, + ?line deep_expect_N(Tracee, B, Q, N-1, + [setelement(2, T, Tracee) || T <- Extra], Tag, R), + ?line Tracee. + +%% Make sure that code that uses the optimized bit syntax matching +%% can be traced without crashing the emulator. (Actually, it seems +%% that we can't trigger the bug using external call trace, but we +%% will keep the test case anyway.) + +bit_syntax(Config) when is_list(Config) -> + ?line start_tracer(), + ?line 1 = trace_func({?MODULE,bs_sum_a,'_'}, []), + ?line 1 = trace_func({?MODULE,bs_sum_b,'_'}, []), + + ?line 6 = call_bs_sum_a(<<1,2,3>>), + ?line 10 = call_bs_sum_b(<<1,2,3,4>>), + + ?line trace_func({?MODULE,'_','_'}, false), + ?line erlang:trace_delivered(all), + receive + {trace_delivered,_,_} -> ok + end, + + Self = self(), + ?line expect({trace,Self,call,{?MODULE,bs_sum_a,[<<2,3>>,1]}}), + ?line expect({trace,Self,call,{?MODULE,bs_sum_b,[1,<<2,3,4>>]}}), + + ok. + +call_bs_sum_a(<<H,T/binary>>) -> + ?MODULE:bs_sum_a(T, H). + +call_bs_sum_b(<<H,T/binary>>) -> + ?MODULE:bs_sum_b(H, T). + +bs_sum_a(<<H,T/binary>>, Acc) -> bs_sum_a(T, H+Acc); +bs_sum_a(<<>>, Acc) -> Acc. + +bs_sum_b(Acc, <<H,T/binary>>) -> bs_sum_b(H+Acc, T); +bs_sum_b(Acc, <<>>) -> Acc. + + + + +%%% Help functions. + +expect() -> + case flush() of + [] -> ok; + Msgs -> + test_server:fail({unexpected,abbr(Msgs)}) + end. + +expect({trace_ts,Pid,Type,MFA,Term,ts}=Message) -> + receive + M -> + case M of + {trace_ts,Pid,Type,MFA,Term,Ts}=MessageTs -> + ok = io:format("Expected and got ~p", [abbr(MessageTs)]), + Ts; + _ -> + io:format("Expected ~p; got ~p", [abbr(Message),abbr(M)]), + test_server:fail({unexpected,abbr([M|flush()])}) + end + after 5000 -> + io:format("Expected ~p; got nothing", [abbr(Message)]), + test_server:fail(no_trace_message) + end; +expect({trace_ts,Pid,Type,MFA,ts}=Message) -> + receive + M -> + case M of + {trace_ts,Pid,Type,MFA,Ts} -> + ok = io:format("Expected and got ~p", [abbr(M)]), + Ts; + _ -> + io:format("Expected ~p; got ~p", [abbr(Message),abbr(M)]), + test_server:fail({unexpected,abbr([M|flush()])}) + end + after 5000 -> + io:format("Expected ~p; got nothing", [abbr(Message)]), + test_server:fail(no_trace_message) + end; +expect(Validator) when is_function(Validator) -> + receive + M -> + case Validator(M) of + expected -> + ok = io:format("Expected and got ~p", [abbr(M)]); + next -> + ok = io:format("Expected and got ~p", [abbr(M)]), + expect(Validator); + {unexpected,Message} -> + io:format("Expected ~p; got ~p", [abbr(Message),abbr(M)]), + test_server:fail({unexpected,abbr([M|flush()])}) + end + after 5000 -> + io:format("Expected ~p; got nothing", [abbr(Validator('_'))]), + test_server:fail(no_trace_message) + end; +expect(Message) -> + receive + M -> + case M of + Message -> + ok = io:format("Expected and got ~p", [abbr(Message)]); + Other -> + io:format("Expected ~p; got ~p", + [abbr(Message),abbr(Other)]), + test_server:fail({unexpected,abbr([Other|flush()])}) + end + after 5000 -> + io:format("Expected ~p; got nothing", [abbr(Message)]), + test_server:fail(no_trace_message) + end. + +trace_info(What, Key) -> + get(tracer) ! {apply,self(),{erlang,trace_info,[What,Key]}}, + Res = receive + {apply_result,Result} -> Result + end, + ok = io:format("erlang:trace_info(~p, ~p) -> ~p", + [What,Key,Res]), + Res. + +trace_func(MFA, MatchSpec) -> + get(tracer) ! {apply,self(),{erlang,trace_pattern,[MFA, MatchSpec]}}, + Res = receive + {apply_result,Result} -> Result + end, + ok = io:format("trace_pattern(~p, ~p) -> ~p", [MFA,MatchSpec,Res]), + Res. + +trace_pid(Pid, On, Flags) -> + get(tracer) ! {apply,self(),{erlang,trace,[Pid,On,Flags]}}, + Res = receive + {apply_result,Result} -> Result + end, + ok = io:format("trace(~p, ~p, ~p) -> ~p", [Pid,On,Flags,Res]), + Res. + +start_tracer() -> + Self = self(), + put(tracer, spawn(fun() -> tracer(Self) end)), + get(tracer). + +start_tracer_loop() -> + Self = self(), + put(tracer, spawn(fun() -> tracer_loop(Self) end)), + get(tracer). + +tracer(RelayTo) -> + erlang:trace(RelayTo, true, [call]), + tracer_loop(RelayTo). + +tracer_loop(RelayTo) -> + receive + {apply,From,{M,F,A}} -> + From ! {apply_result,apply(M, F, A)}, + tracer_loop(RelayTo); + Msg -> + RelayTo ! Msg, + tracer_loop(RelayTo) + end. + +id(I) -> I. + +deep(N, Class, Reason) -> + try ?MODULE:deep_1(N, Class, Reason) of + Value -> {value,Value} + catch C:R -> {C,R} + end. + +deep_1(1, Class, Reason) -> + ?MODULE:deep_2(Class, Reason); +deep_1(N, Class, Reason) when is_integer(N), N > 1 -> + ?MODULE:deep_1(N-1, Class, Reason). + +deep_2(Class, Reason) -> + ?MODULE:deep_4(?MODULE:deep_3(Class, Reason)). + +deep_3(Class, Reason) -> + {Class,Reason}. + +deep_4(CR) -> + case ?MODULE:id(CR) of + {exit,[Reason]} -> + erlang:exit(Reason); + {throw,[Reason]} -> + erlang:throw(Reason); + {error,[Reason,Arglist]} -> + erlang:error(Reason, Arglist); + {error,[Reason]} -> + erlang:error(Reason); + {id,[Reason]} -> + Reason; + {reverse,[A,B]} -> + lists:reverse(A, B); + {append,[A,B]} -> + A ++ B; + {apply,[Fun,Args]} -> + erlang:apply(Fun, Args); + {apply,[M,F,Args]} -> + erlang:apply(M, F, Args); + {deep_5,[A,B]} -> + ?MODULE:deep_5(A, B); + {deep_5,[A]} -> + ?MODULE:deep_5(A); + {'=',[A,B]} -> + A = B + end. + +deep_5(A) when is_integer(A) -> + A. + +flush() -> + receive X -> + [X|flush()] + after 1000 -> + [] + end. + +%% Abbreviate large complex terms +abbr(Term) -> + abbr(Term, 20). +%% +abbr(Tuple, N) when is_tuple(Tuple) -> + abbr_tuple(Tuple, 1, N, []); +abbr(List, N) when is_list(List) -> + abbr_list(List, N, []); +abbr(Term, _) -> Term. +%% +abbr_tuple(_, _, 0, R) -> + list_to_tuple(reverse(R, ['...'])); +abbr_tuple(Tuple, J, N, R) when J =< size(Tuple) -> + M = N-1, + abbr_tuple(Tuple, J+1, M, [abbr(element(J, Tuple), M)|R]); +abbr_tuple(_, _, _, R) -> + list_to_tuple(reverse(R)). +%% +abbr_list(_, 0, R) -> + case io_lib:printable_list(R) of + true -> + reverse(R, "..."); + false -> + reverse(R, '...') + end; +abbr_list([H|T], N, R) -> + M = N-1, + abbr_list(T, M, [abbr(H, M)|R]); +abbr_list(T, _, R) -> + reverse(R, T). + +%% Lean and mean list functions + +%% Do not build garbage +seq(M, N, R) when M =< N -> + seq(M, N-1, [N|R]); +seq(_, _, R) -> R. + +%% lists:reverse can not be called since it is traced +reverse(L) -> + reverse(L, []). +%% +reverse([], R) -> R; +reverse([H|T], R) -> + reverse(T, [H|R]). diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl new file mode 100644 index 0000000000..33351a3cc9 --- /dev/null +++ b/erts/emulator/test/code_SUITE.erl @@ -0,0 +1,520 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(code_SUITE). +-export([all/1, + new_binary_types/1,t_check_process_code/1,t_check_process_code_ets/1, + external_fun/1,get_chunk/1,module_md5/1,make_stub/1, + make_stub_many_funs/1,constant_pools/1, + false_dependency/1,coverage/1]). + +-include("test_server.hrl"). + +all(suite) -> + [new_binary_types,t_check_process_code,t_check_process_code_ets, + external_fun,get_chunk,module_md5,make_stub,make_stub_many_funs, + constant_pools,false_dependency,coverage]. + +new_binary_types(Config) when is_list(Config) -> + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "my_code_test"), + ?line {ok,my_code_test,Bin} = compile:file(File, [binary]), + ?line {module,my_code_test} = erlang:load_module(my_code_test, + make_sub_binary(Bin)), + ?line true = erlang:delete_module(my_code_test), + ?line true = erlang:purge_module(my_code_test), + + ?line {module,my_code_test} = erlang:load_module(my_code_test, + make_unaligned_sub_binary(Bin)), + ?line true = erlang:delete_module(my_code_test), + ?line true = erlang:purge_module(my_code_test), + + %% Try heap binaries and bad binaries. + ?line {error,badfile} = erlang:load_module(my_code_test, <<1,2>>), + ?line {error,badfile} = erlang:load_module(my_code_test, + make_sub_binary(<<1,2>>)), + ?line {error,badfile} = erlang:load_module(my_code_test, + make_unaligned_sub_binary(<<1,2>>)), + ?line {'EXIT',{badarg,_}} = (catch erlang:load_module(my_code_test, + bit_sized_binary(Bin))), + ok. + +t_check_process_code(doc) -> "Test check_process_code/2."; +t_check_process_code(Config) when is_list(Config) -> + case erlang:system_info(heap_type) of + private -> t_check_process_code_1(Config); + hybrid -> {skip,"Hybrid heap"} + end. + +t_check_process_code_1(Config) -> + ?line Priv = ?config(priv_dir, Config), + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "my_code_test"), + ?line Code = filename:join(Priv, "my_code_test"), + + ?line {ok,my_code_test} = c:c(File, [{outdir,Priv}]), + + ?line MyFun = fun(X, Y) -> X + Y end, %Confuse things. + ?line F = my_code_test:make_fun(42), + ?line 2 = fun_refc(F), + ?line MyFun2 = fun(X, Y) -> X * Y end, %Confuse things. + ?line 44 = F(2), + + %% Delete the module and call the fun again. + ?line true = erlang:delete_module(my_code_test), + ?line 2 = fun_refc(F), + ?line 45 = F(3), + ?line {'EXIT',{undef,_}} = (catch my_code_test:make_fun(33)), + + %% The fun should still be there, preventing purge. + ?line true = erlang:check_process_code(self(), my_code_test), + gc(), + gc(), %Place funs on the old heap. + ?line true = erlang:check_process_code(self(), my_code_test), + + %% Using the funs here guarantees that they will not be prematurely garbed. + ?line 48 = F(6), + ?line 3 = MyFun(1, 2), + ?line 12 = MyFun2(3, 4), + + %% Kill all funs. + t_check_process_code1(Code, []). + +%% The real fun was killed, but we have some fakes which look similar. + +t_check_process_code1(Code, Fakes) -> + ?line MyFun = fun(X, Y) -> X + Y + 1 end, %Confuse things. + ?line false = erlang:check_process_code(self(), my_code_test), + ?line 4 = MyFun(1, 2), + t_check_process_code2(Code, Fakes). + +t_check_process_code2(Code, _) -> + ?line false = erlang:check_process_code(self(), my_code_test), + ?line true = erlang:purge_module(my_code_test), + + %% In the next test we will load the same module twice. + ?line {module,my_code_test} = code:load_abs(Code), + ?line F = my_code_test:make_fun(37), + ?line 2 = fun_refc(F), + ?line false = erlang:check_process_code(self(), my_code_test), + ?line {module,my_code_test} = code:load_abs(Code), + ?line 2 = fun_refc(F), + + %% Still false because the fun with the same identify is found + %% in the current code. + ?line false = erlang:check_process_code(self(), my_code_test), + + %% Some fake funs in the same module should not do any difference. + ?line false = erlang:check_process_code(self(), my_code_test), + + 38 = F(1), + t_check_process_code3(Code, F, []). + +t_check_process_code3(Code, F, Fakes) -> + Pid = spawn_link(fun() -> body(F, Fakes) end), + ?line true = erlang:purge_module(my_code_test), + ?line false = erlang:check_process_code(self(), my_code_test), + ?line false = erlang:check_process_code(Pid, my_code_test), + + ?line true = erlang:delete_module(my_code_test), + ?line true = erlang:check_process_code(self(), my_code_test), + ?line true = erlang:check_process_code(Pid, my_code_test), + 39 = F(2), + t_check_process_code4(Code, Pid). + +t_check_process_code4(_Code, Pid) -> + Pid ! drop_funs, + receive after 1 -> ok end, + ?line false = erlang:check_process_code(Pid, my_code_test), + ok. + +body(F, Fakes) -> + receive + jog -> + 40 = F(3), + erlang:garbage_collect(), + body(F, Fakes); + drop_funs -> + dropped_body() + end. + +dropped_body() -> + receive + X -> exit(X) + end. + +gc() -> + erlang:garbage_collect(), + gc1(). +gc1() -> ok. + +t_check_process_code_ets(doc) -> + "Test check_process_code/2 in combination with a fun obtained from an ets table."; +t_check_process_code_ets(Config) when is_list(Config) -> + case {test_server:is_native(?MODULE),erlang:system_info(heap_type)} of + {true,_} -> + {skipped,"Native code"}; + {_,hybrid} -> + {skipped,"Hybrid heap"}; + {false,private} -> + do_check_process_code_ets(Config) + end. + +do_check_process_code_ets(Config) -> + ?line Priv = ?config(priv_dir, Config), + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "my_code_test"), + + ?line erlang:purge_module(my_code_test), + ?line erlang:delete_module(my_code_test), + ?line {ok,my_code_test} = c:c(File, [{outdir,Priv}]), + + ?line T = ets:new(my_code_test, []), + ?line ets:insert(T, {7,my_code_test:make_fun(107)}), + ?line ets:insert(T, {8,my_code_test:make_fun(108)}), + ?line erlang:delete_module(my_code_test), + ?line false = erlang:check_process_code(self(), my_code_test), + Body = fun() -> + [{7,F1}] = ets:lookup(T, 7), + [{8,F2}] = ets:lookup(T, 8), + IdleLoop = fun() -> receive _X -> ok end end, + RecLoop = fun(Again) -> + receive + call -> 110 = F1(3), + 100 = F2(-8), + Again(Again); + {drop_funs,To} -> + To ! funs_dropped, + IdleLoop() + end + end, + true = erlang:check_process_code(self(), my_code_test), + RecLoop(RecLoop) + end, + ?line Pid = spawn_link(Body), + receive after 1 -> ok end, + ?line true = erlang:check_process_code(Pid, my_code_test), + Pid ! call, + Pid ! {drop_funs,self()}, + + receive + funs_dropped -> ok; + Other -> ?t:fail({unexpected,Other}) + after 10000 -> + ?line ?t:fail(no_funs_dropped_answer) + end, + + ?line false = erlang:check_process_code(Pid, my_code_test), + ok. + +fun_refc(F) -> + {refc,Count} = erlang:fun_info(F, refc), + Count. + + +external_fun(Config) when is_list(Config) -> + ?line false = erlang:function_exported(another_code_test, x, 1), + ?line ExtFun = erlang:make_fun(id(another_code_test), x, 1), + ?line {'EXIT',{undef,_}} = (catch ExtFun(answer)), + ?line false = erlang:function_exported(another_code_test, x, 1), + ?line false = lists:member(another_code_test, erlang:loaded()), + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "another_code_test"), + ?line {ok,another_code_test,Code} = compile:file(File, [binary,report]), + ?line {module,another_code_test} = erlang:load_module(another_code_test, Code), + ?line 42 = ExtFun(answer), + ok. + +get_chunk(Config) when is_list(Config) -> + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "my_code_test"), + ?line {ok,my_code_test,Code} = compile:file(File, [binary]), + + %% Should work. + ?line Chunk = get_chunk_ok("Atom", Code), + ?line Chunk = get_chunk_ok("Atom", make_sub_binary(Code)), + ?line Chunk = get_chunk_ok("Atom", make_unaligned_sub_binary(Code)), + + %% Should fail. + ?line {'EXIT',{badarg,_}} = (catch code:get_chunk(bit_sized_binary(Code), "Atom")), + ?line {'EXIT',{badarg,_}} = (catch code:get_chunk(Code, "bad chunk id")), + + %% Invalid beam code or missing chunk should return 'undefined'. + ?line undefined = code:get_chunk(<<"not a beam module">>, "Atom"), + ?line undefined = code:get_chunk(Code, "XXXX"), + + ok. + +get_chunk_ok(Chunk, Code) -> + case code:get_chunk(Code, Chunk) of + Bin when is_binary(Bin) -> Bin + end. + +module_md5(Config) when is_list(Config) -> + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "my_code_test"), + ?line {ok,my_code_test,Code} = compile:file(File, [binary]), + + %% Should work. + ?line Chunk = module_md5_ok(Code), + ?line Chunk = module_md5_ok(make_sub_binary(Code)), + ?line Chunk = module_md5_ok(make_unaligned_sub_binary(Code)), + + %% Should fail. + ?line {'EXIT',{badarg,_}} = (catch code:module_md5(bit_sized_binary(Code))), + + %% Invalid beam code should return 'undefined'. + ?line undefined = code:module_md5(<<"not a beam module">>), + ok. + +module_md5_ok(Code) -> + case code:module_md5(Code) of + Bin when is_binary(Bin), size(Bin) =:= 16 -> Bin + end. + + +make_stub(Config) when is_list(Config) -> + %% No old code to purge if hybrid heap because of skipped test cases, + %% so we'll need a catch here. + ?line (catch erlang:purge_module(my_code_test)), + + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "my_code_test"), + ?line {ok,my_code_test,Code} = compile:file(File, [binary]), + + ?line my_code_test = code:make_stub_module(my_code_test, Code, {[],[]}), + ?line true = erlang:delete_module(my_code_test), + ?line true = erlang:purge_module(my_code_test), + + ?line my_code_test = code:make_stub_module(my_code_test, + make_unaligned_sub_binary(Code), + {[],[]}), + ?line true = erlang:delete_module(my_code_test), + ?line true = erlang:purge_module(my_code_test), + + ?line my_code_test = code:make_stub_module(my_code_test, zlib:gzip(Code), + {[],[]}), + ?line true = erlang:delete_module(my_code_test), + ?line true = erlang:purge_module(my_code_test), + + %% Should fail. + ?line {'EXIT',{badarg,_}} = + (catch code:make_stub_module(my_code_test, <<"bad">>, {[],[]})), + ?line {'EXIT',{badarg,_}} = + (catch code:make_stub_module(my_code_test, + bit_sized_binary(Code), + {[],[]})), + ok. + +make_stub_many_funs(Config) when is_list(Config) -> + %% No old code to purge if hybrid heap because of skipped test cases, + %% so we'll need a catch here. + ?line (catch erlang:purge_module(many_funs)), + + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "many_funs"), + ?line {ok,many_funs,Code} = compile:file(File, [binary]), + + ?line many_funs = code:make_stub_module(many_funs, Code, {[],[]}), + ?line true = erlang:delete_module(many_funs), + ?line true = erlang:purge_module(many_funs), + ?line many_funs = code:make_stub_module(many_funs, + make_unaligned_sub_binary(Code), + {[],[]}), + ?line true = erlang:delete_module(many_funs), + ?line true = erlang:purge_module(many_funs), + + %% Should fail. + ?line {'EXIT',{badarg,_}} = + (catch code:make_stub_module(many_funs, <<"bad">>, {[],[]})), + ?line {'EXIT',{badarg,_}} = + (catch code:make_stub_module(many_funs, + bit_sized_binary(Code), + {[],[]})), + ok. + +constant_pools(Config) when is_list(Config) -> + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "literals"), + ?line {ok,literals,Code} = compile:file(File, [report,binary,constant_pool]), + ?line {module,literals} = erlang:load_module(literals, + make_sub_binary(Code)), + + %% Initialize. + ?line A = literals:a(), + ?line B = literals:b(), + ?line C = literals:huge_bignum(), + ?line process_flag(trap_exit, true), + Self = self(), + + %% Have a process WITHOUT old heap that references the literals + %% in the 'literals' module. + ?line NoOldHeap = spawn_link(fun() -> no_old_heap(Self) end), + receive go -> ok end, + ?line true = erlang:delete_module(literals), + ?line false = erlang:check_process_code(NoOldHeap, literals), + ?line erlang:check_process_code(self(), literals), + ?line true = erlang:purge_module(literals), + ?line NoOldHeap ! done, + ?line receive + {'EXIT',NoOldHeap,{A,B,C}} -> + ok; + Other -> + ?line ?t:fail({unexpected,Other}) + end, + ?line {module,literals} = erlang:load_module(literals, Code), + + %% Have a process WITH an old heap that references the literals + %% in the 'literals' module. + ?line OldHeap = spawn_link(fun() -> old_heap(Self) end), + receive go -> ok end, + ?line true = erlang:delete_module(literals), + ?line false = erlang:check_process_code(OldHeap, literals), + ?line erlang:check_process_code(self(), literals), + ?line erlang:purge_module(literals), + ?line OldHeap ! done, + receive + {'EXIT',OldHeap,{A,B,C,[1,2,3|_]=Seq}} when length(Seq) =:= 16 -> + ok + end. + +no_old_heap(Parent) -> + A = literals:a(), + B = literals:b(), + Res = {A,B,literals:huge_bignum()}, + Parent ! go, + receive + done -> + exit(Res) + end. + +old_heap(Parent) -> + A = literals:a(), + B = literals:b(), + Res = {A,B,literals:huge_bignum(),lists:seq(1, 16)}, + create_old_heap(), + Parent ! go, + receive + done -> + exit(Res) + end. + +create_old_heap() -> + case process_info(self(), [heap_size,total_heap_size]) of + [{heap_size,Sz},{total_heap_size,Total}] when Sz < Total -> + ok; + _ -> + create_old_heap() + end. + +%% OTP-7559: c_p->cp could contain garbage and create a false dependency +%% to a module in a process. (Thanks to Richard Carlsson.) +false_dependency(Config) when is_list(Config) -> + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "cpbugx"), + ?line {ok,cpbugx,Code} = compile:file(File, [binary,report]), + + do_false_dependency(fun cpbugx:before/0, Code), + do_false_dependency(fun cpbugx:before2/0, Code), + do_false_dependency(fun cpbugx:before3/0, Code), + +%% %% Spawn process. Make sure it has called cpbugx:before/0 and returned. +%% Parent = self(), +%% ?line Pid = spawn_link(fun() -> false_dependency_loop(Parent) end), +%% ?line receive initialized -> ok end, + +%% %% Reload the module. Make sure the process is still alive. +%% ?line {module,cpbugx} = erlang:load_module(cpbugx, Bin), +%% ?line io:put_chars(binary_to_list(element(2, process_info(Pid, backtrace)))), +%% ?line true = is_process_alive(Pid), + +%% %% There should not be any dependency to cpbugx. +%% ?line false = erlang:check_process_code(Pid, cpbugx), + + + + +%% %% Kill the process. +%% ?line unlink(Pid), exit(Pid, kill), + ok. + +do_false_dependency(Init, Code) -> + ?line {module,cpbugx} = erlang:load_module(cpbugx, Code), + + %% Spawn process. Make sure it has the appropriate init function + %% and returned. CP should not contain garbage after the return. + Parent = self(), + ?line Pid = spawn_link(fun() -> false_dependency_loop(Parent, Init) end), + ?line receive initialized -> ok end, + + %% Reload the module. Make sure the process is still alive. + ?line {module,cpbugx} = erlang:load_module(cpbugx, Code), + ?line io:put_chars(binary_to_list(element(2, process_info(Pid, backtrace)))), + ?line true = is_process_alive(Pid), + + %% There should not be any dependency to cpbugx. + ?line false = erlang:check_process_code(Pid, cpbugx), + + %% Kill the process and completely unload the code. + ?line unlink(Pid), exit(Pid, kill), + ?line true = erlang:purge_module(cpbugx), + ?line true = erlang:delete_module(cpbugx), + ?line true = erlang:purge_module(cpbugx), + ok. + +false_dependency_loop(Parent, Init) -> + Init(), + Parent ! initialized, + receive + _ -> false_dependency_loop(Parent, Init) + end. + +coverage(Config) when is_list(Config) -> + ?line code:is_module_native(?MODULE), + ?line {'EXIT',{badarg,_}} = (catch erlang:purge_module({a,b,c})), + ?line {'EXIT',{badarg,_}} = (catch code:is_module_native({a,b,c})), + ?line {'EXIT',{badarg,_}} = (catch erlang:check_process_code(not_a_pid, ?MODULE)), + ?line {'EXIT',{badarg,_}} = (catch erlang:check_process_code(self(), [not_a_module])), + ?line {'EXIT',{badarg,_}} = (catch erlang:delete_module([a,b,c])), + ?line {'EXIT',{badarg,_}} = (catch erlang:module_loaded(42)), + ok. + +%% Utilities. + +make_sub_binary(Bin) when is_binary(Bin) -> + {_,B1} = split_binary(list_to_binary([0,1,3,Bin,4,5,6,7]), 3), + {B,_} = split_binary(B1, size(Bin)), + B; +make_sub_binary(List) -> + make_sub_binary(list_to_binary(List)). + +make_unaligned_sub_binary(Bin0) -> + Bin1 = <<0:3,Bin0/binary,31:5>>, + Sz = size(Bin0), + <<0:3,Bin:Sz/binary,31:5>> = id(Bin1), + Bin. + +%% Add 1 bit to the size of the binary. +bit_sized_binary(Bin0) -> + Bin = <<Bin0/binary,1:1>>, + BitSize = bit_size(Bin), + BitSize = 8*size(Bin) + 1, + Bin. + +id(I) -> I. diff --git a/erts/emulator/test/code_SUITE_data/another_code_test.erl b/erts/emulator/test/code_SUITE_data/another_code_test.erl new file mode 100644 index 0000000000..1c9b5bdb5b --- /dev/null +++ b/erts/emulator/test/code_SUITE_data/another_code_test.erl @@ -0,0 +1,23 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(another_code_test). +-export([x/1]). + +x(answer) -> 42. diff --git a/erts/emulator/test/code_SUITE_data/cpbugx.erl b/erts/emulator/test/code_SUITE_data/cpbugx.erl new file mode 100644 index 0000000000..fb617c1973 --- /dev/null +++ b/erts/emulator/test/code_SUITE_data/cpbugx.erl @@ -0,0 +1,45 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(cpbugx). + +-export([before/0,before2/0,before3/0]). + +before() -> + 1 + lethal(). + +lethal() -> + 4711. + +before2() -> + {status,lethal2(self())}. + +lethal2(Pid) -> + try + is_process_alive(Pid) + catch + _ -> + error + end. + +before3() -> + atom_to_list(lethal3(self())). + +lethal3(Pid) -> + Pid ! garbage. diff --git a/erts/emulator/test/code_SUITE_data/literals.erl b/erts/emulator/test/code_SUITE_data/literals.erl new file mode 100644 index 0000000000..9f99b1a780 --- /dev/null +++ b/erts/emulator/test/code_SUITE_data/literals.erl @@ -0,0 +1,83 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(literals). +-export([a/0,b/0,huge_bignum/0]). + +a() -> + {a,42.0,[7,38877938333399637266518333334747]}. + +b() -> + [{init,get_flag,1}, + {init,get_flags,0}, + {init,get_args,0}, + {string,re_sh_to_awk,1}, + {string,re_parse,1}, + {string,re_match,2}, + {string,re_sub,3}, + {string,re_gsub,3}, + {string,re_split,2}, + {string,index,2}, + {erl_eval,seq,2}, + {erl_eval,seq,3}, + {erl_eval,arg_list,2}, + {erl_eval,arg_list,3}, + {erl_pp,seq,1}, + {erl_pp,seq,2}, + {io,scan_erl_seq,1}, + {io,scan_erl_seq,2}, + {io,scan_erl_seq,3}, + {io,parse_erl_seq,1}, + {io,parse_erl_seq,2}, + {io,parse_erl_seq,3}, + {io,parse_exprs,2}, + {io_lib,scan,1}, + {io_lib,scan,2}, + {io_lib,scan,3}, + {io_lib,reserved_word,1}, + {lists,keymap,4}, + {lists,all,3}, + {lists,any,3}, + {lists,map,3}, + {lists,flatmap,3}, + {lists,foldl,4}, + {lists,foldr,4}, + {lists,mapfoldl,4}, + {lists,mapfoldr,4}, + {lists,filter,3}, + {lists,foreach,3}, + {erlang,old_binary_to_term,1}, + {erlang,info,1}, + {file,file_info,1}, + {dict,dict_to_list,1}, + {dict,list_to_dict,1}, + {orddict,dict_to_list,1}, + {orddict,list_to_dict,1}, + {sets,new_set,0}, + {sets,set_to_list,1}, + {sets,list_to_set,1}, + {sets,subset,2}, + {ordsets,new_set,0}, + {ordsets,set_to_list,1}, + {ordsets,list_to_set,1}, + {ordsets,subset,2}, + {calendar,local_time_to_universal_time,1}]. + +huge_bignum() -> + 36#9987333333392789234879423987243987423432879423879234897423879423874328794323248423872348742323487423987423879243872347824374238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR0737376766798779987333333392789234879423987243987423432879423879234897423879423874328794323248423872348742323487423987423879243872347824374238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987779JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR0737376766798779987333333392789234879423987243987423432879423879234897423879423874328794323248423872348742323487423987423879243872347824374238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR073737676679877. diff --git a/erts/emulator/test/code_SUITE_data/many_funs.erl b/erts/emulator/test/code_SUITE_data/many_funs.erl new file mode 100644 index 0000000000..0f9c3a85a4 --- /dev/null +++ b/erts/emulator/test/code_SUITE_data/many_funs.erl @@ -0,0 +1,47 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(many_funs). + +-export([make_fun/1,many_funs/0]). + +make_fun(A) -> + fun(X) -> A + X end. + +%% Force dynamic allocation of lambda table. +many_funs() -> + [fun(_) -> 1 end, + fun(_) -> 2 end, + fun(_) -> 3 end, + fun(_) -> 4 end, + fun(_) -> 5 end, + fun(_) -> 6 end, + fun(_) -> 7 end, + fun(_) -> 8 end, + fun(_) -> 9 end, + fun(_) -> 10 end, + fun(_) -> 11 end, + fun(_) -> 12 end, + fun(_) -> 13 end, + fun(_) -> 14 end, + fun(_) -> 15 end, + fun(_) -> 16 end]. + + + diff --git a/erts/emulator/test/code_SUITE_data/my_code_test.erl b/erts/emulator/test/code_SUITE_data/my_code_test.erl new file mode 100644 index 0000000000..5039b7f937 --- /dev/null +++ b/erts/emulator/test/code_SUITE_data/my_code_test.erl @@ -0,0 +1,27 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(my_code_test). + +-export([make_fun/1]). + +make_fun(A) -> + fun(X) -> A + X end. + + diff --git a/erts/emulator/test/crypto_SUITE.erl b/erts/emulator/test/crypto_SUITE.erl new file mode 100644 index 0000000000..e3d34b923d --- /dev/null +++ b/erts/emulator/test/crypto_SUITE.erl @@ -0,0 +1,330 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(crypto_SUITE). + +-include("test_server.hrl"). + +-export([all/1, + t_md5/1,t_md5_update/1,error/1,unaligned_context/1,random_lists/1, + misc_errors/1]). + +all(suite) -> + [t_md5,t_md5_update,error,unaligned_context,random_lists,misc_errors]. + + +misc_errors(doc) -> + ["Test crc32, adler32 and md5 error cases not covered by other tests"]; +misc_errors(suite) -> + []; +misc_errors(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(2)), + ?line 1 = erlang:adler32([]), + ?line L = lists:duplicate(600,3), + ?line 1135871753 = erlang:adler32(L), + ?line L2 = lists:duplicate(22000,3), + ?line 1100939744 = erlang:adler32(L2), + ?line {'EXIT', {badarg,_}} = (catch erlang:adler32(L++[a])), + ?line {'EXIT', {badarg,_}} = (catch erlang:crc32(L++[a])), + ?line {'EXIT', {badarg,_}} = (catch erlang:crc32([1,2,3|<<25:7>>])), + ?line {'EXIT', {badarg,_}} = (catch erlang:crc32([1,2,3|4])), + ?line Big = 111111111111111111111111111111, + ?line {'EXIT', {badarg,_}} = (catch erlang:crc32(Big,<<"hej">>)), + ?line {'EXIT', {badarg,_}} = (catch erlang:crc32(25,[1,2,3|4])), + ?line {'EXIT', {badarg,_}} = (catch erlang:crc32_combine(Big,3,3)), + ?line {'EXIT', {badarg,_}} = (catch erlang:crc32_combine(3,Big,3)), + ?line {'EXIT', {badarg,_}} = (catch erlang:crc32_combine(3,3,Big)), + ?line {'EXIT', {badarg,_}} = (catch erlang:adler32(Big,<<"hej">>)), + ?line {'EXIT', {badarg,_}} = (catch erlang:adler32(25,[1,2,3|4])), + ?line {'EXIT', {badarg,_}} = (catch erlang:adler32_combine(Big,3,3)), + ?line {'EXIT', {badarg,_}} = (catch erlang:adler32_combine(3,Big,3)), + ?line {'EXIT', {badarg,_}} = (catch erlang:adler32_combine(3,3,Big)), + ?line {'EXIT', {badarg,_}} = (catch erlang:md5_update(<<"hej">>,<<"hej">>)), + ?line {'EXIT', {badarg,_}} = (catch erlang:md5_final(<<"hej">>)), + ?line test_server:timetrap_cancel(Dog), + ok. + + +%% +%% Most of the real code for these test cases are in +%% the modules crypto_reference and random_iolist. +%% +-define(REF,crypto_reference). + +nicesplit(N,L) -> + nicesplit(N,L,[]). +nicesplit(0,Tail,Acc) -> + {lists:reverse(Acc),Tail}; +nicesplit(_,[],Acc) -> + {lists:reverse(Acc),[]}; +nicesplit(N,[H|Tail],Acc) -> + nicesplit(N-1,Tail,[H|Acc]). + +run_in_para([],_) -> + true; +run_in_para(FunList,Schedulers) -> + {ThisTime,NextTime} = nicesplit(Schedulers,FunList), + case length(ThisTime) of + 1 -> + [{L,Fun}] = ThisTime, + try + Fun() + catch + _:Reason -> + exit({error_at_line,L,Reason}) + end; + _ -> + These = [ {L,erlang:spawn_monitor(F)} || {L,F} <- ThisTime ], + collect_workers(These) + end, + run_in_para(NextTime,Schedulers). + +collect_workers([]) -> + ok; +collect_workers([{L,{Pid,Ref}}|T]) -> + receive + {'DOWN',Ref,process,Pid,normal} -> + collect_workers(T); + {'DOWN',Ref,process,Pid,Other} -> + exit({error_at_line,L,Other}) + end. + +random_lists(doc) -> + ["Test crc32, adler32 and md5 on a number of pseudo-randomly generated " + "lists."]; +random_lists(suite) -> + []; +random_lists(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(5)), + ?line Num = erlang:system_info(schedulers_online), + ?line B = list_to_binary( + lists:duplicate( + (erlang:system_info(context_reductions)*10) - 50,$!)), + ?line CRC32_1 = fun(L) -> erlang:crc32(L) end, + ?line CRC32_2 = fun(L) -> ?REF:crc32(L) end, + ?line ADLER32_1 = fun(L) -> erlang:adler32(L) end, + ?line ADLER32_2 = fun(L) -> ?REF:adler32(L) end, + ?line MD5_1 = fun(L) -> erlang:md5(L) end, + ?line MD5_2 = fun(L) -> ?REF:md5_final( + ?REF:md5_update(?REF:md5_init(),L)) end, + ?line MD5_3 = fun(L) -> erlang:md5_final( + erlang:md5_update(erlang:md5_init(),L)) end, + ?line CRC32_1_L = fun(L) -> erlang:crc32([B|L]) end, + ?line CRC32_2_L = fun(L) -> ?REF:crc32([B|L]) end, + ?line ADLER32_1_L = fun(L) -> erlang:adler32([B|L]) end, + ?line ADLER32_2_L = fun(L) -> ?REF:adler32([B|L]) end, + ?line MD5_1_L = fun(L) -> erlang:md5([B|L]) end, + ?line MD5_2_L = fun(L) -> ?REF:md5_final( + ?REF:md5_update(?REF:md5_init(),[B|L])) end, + ?line MD5_3_L = fun(L) -> erlang:md5_final( + erlang:md5_update( + erlang:md5_init(),[B|L])) end, + ?line Wlist0 = + [{?LINE, fun() -> random_iolist:run(150, CRC32_1, CRC32_2) end}, + {?LINE, fun() -> random_iolist:run(150, ADLER32_1, ADLER32_2) end}, + {?LINE, fun() -> random_iolist:run(150,MD5_1,MD5_2) end}, + {?LINE, fun() -> random_iolist:run(150,MD5_1,MD5_3) end}, + {?LINE, fun() -> random_iolist:run(150, CRC32_1_L, CRC32_2_L) end}, + {?LINE, + fun() -> random_iolist:run(150, ADLER32_1_L, ADLER32_2_L) end}, + {?LINE, fun() -> random_iolist:run(150,MD5_1_L,MD5_2_L) end}, + {?LINE, fun() -> random_iolist:run(150,MD5_1_L,MD5_3_L) end}], + ?line run_in_para(Wlist0,Num), + ?line CRC32_1_2 = fun(L1,L2) -> erlang:crc32([L1,L2]) end, + ?line CRC32_2_2 = fun(L1,L2) -> erlang:crc32(erlang:crc32(L1),L2) end, + ?line CRC32_3_2 = fun(L1,L2) -> erlang:crc32_combine( + erlang:crc32(L1), + erlang:crc32(L2), + erlang:iolist_size(L2)) + end, + ?line ADLER32_1_2 = fun(L1,L2) -> erlang:adler32([L1,L2]) end, + ?line ADLER32_2_2 = fun(L1,L2) -> erlang:adler32( + erlang:adler32(L1),L2) end, + ?line ADLER32_3_2 = fun(L1,L2) -> erlang:adler32_combine( + erlang:adler32(L1), + erlang:adler32(L2), + erlang:iolist_size(L2)) + end, + ?line MD5_1_2 = fun(L1,L2) -> erlang:md5([L1,L2]) end, + ?line MD5_2_2 = fun(L1,L2) -> + erlang:md5_final( + erlang:md5_update( + erlang:md5_update( + erlang:md5_init(), + L1), + L2)) + end, + ?line CRC32_1_L_2 = fun(L1,L2) -> erlang:crc32([[B|L1],[B|L2]]) end, + ?line CRC32_2_L_2 = fun(L1,L2) -> erlang:crc32( + erlang:crc32([B|L1]),[B|L2]) end, + ?line CRC32_3_L_2 = fun(L1,L2) -> erlang:crc32_combine( + erlang:crc32([B|L1]), + erlang:crc32([B|L2]), + erlang:iolist_size([B|L2])) + end, + ?line ADLER32_1_L_2 = fun(L1,L2) -> erlang:adler32([[B|L1],[B|L2]]) end, + ?line ADLER32_2_L_2 = fun(L1,L2) -> erlang:adler32( + erlang:adler32([B|L1]), + [B|L2]) + end, + ?line ADLER32_3_L_2 = fun(L1,L2) -> erlang:adler32_combine( + erlang:adler32([B|L1]), + erlang:adler32([B|L2]), + erlang:iolist_size([B|L2])) + end, + ?line MD5_1_L_2 = fun(L1,L2) -> erlang:md5([[B|L1],[B|L2]]) end, + ?line MD5_2_L_2 = fun(L1,L2) -> + erlang:md5_final( + erlang:md5_update( + erlang:md5_update( + erlang:md5_init(), + [B|L1]), + [B|L2])) + end, + ?line Wlist1 = + [{?LINE, fun() -> random_iolist:run2(150,CRC32_1_2,CRC32_2_2) end}, + {?LINE, fun() -> random_iolist:run2(150,CRC32_1_2,CRC32_3_2) end}, + {?LINE, fun() -> random_iolist:run2(150,ADLER32_1_2,ADLER32_2_2) end}, + {?LINE, fun() -> random_iolist:run2(150,ADLER32_1_2,ADLER32_3_2) end}, + {?LINE, fun() -> random_iolist:run2(150,MD5_1_2,MD5_2_2) end}, + {?LINE, fun() -> random_iolist:run2(150,CRC32_1_L_2,CRC32_2_L_2) end}, + {?LINE, fun() -> random_iolist:run2(150,CRC32_1_L_2,CRC32_3_L_2) end}, + {?LINE, + fun() -> random_iolist:run2(150,ADLER32_1_L_2,ADLER32_2_L_2) end}, + {?LINE, + fun() -> random_iolist:run2(150,ADLER32_1_L_2,ADLER32_3_L_2) end}, + {?LINE, fun() -> random_iolist:run2(150,MD5_1_L_2,MD5_2_L_2) end}], + ?line run_in_para(Wlist1,Num), + ?line test_server:timetrap_cancel(Dog), + ok. + +%% +%% +t_md5(doc) -> + ["Generate MD5 message digests and check the result. Examples are " + "from RFC-1321."]; +t_md5(Config) when is_list(Config) -> + ?line t_md5_test("", "d41d8cd98f00b204e9800998ecf8427e"), + ?line t_md5_test("a", "0cc175b9c0f1b6a831c399e269772661"), + ?line t_md5_test("abc", "900150983cd24fb0d6963f7d28e17f72"), + ?line t_md5_test(["message ","digest"], "f96b697d7cb7938d525a2f31aaf161d0"), + ?line t_md5_test(["message ",unaligned_sub_bin(<<"digest">>)], + "f96b697d7cb7938d525a2f31aaf161d0"), + ?line t_md5_test("abcdefghijklmnopqrstuvwxyz", + "c3fcd3d76192e4007dfb496cca67e13b"), + ?line t_md5_test("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789", + "d174ab98d277d9f5a5611c2c9f419d9f"), + ?line t_md5_test("12345678901234567890123456789012345678901234567890" + "123456789012345678901234567890", + "57edf4a22be3c955ac49da2e2107b67a"), + ok. + +%% +%% +t_md5_update(doc) -> + ["Generate MD5 message using md5_init, md5_update, and md5_final, and" + "check the result. Examples are from RFC-1321."]; +t_md5_update(Config) when is_list(Config) -> + ?line t_md5_update_1(fun(Str) -> Str end), + ?line t_md5_update_1(fun(Str) -> list_to_binary(Str) end), + ?line t_md5_update_1(fun(Str) -> unaligned_sub_bin(list_to_binary(Str)) end), + ok. + +t_md5_update_1(Tr) when is_function(Tr, 1) -> + Ctx = erlang:md5_init(), + Ctx1 = erlang:md5_update(Ctx, Tr("ABCDEFGHIJKLMNOPQRSTUVWXYZ")), + Ctx2 = erlang:md5_update(Ctx1, Tr("abcdefghijklmnopqrstuvwxyz" + "0123456789")), + m(erlang:md5_final(Ctx2), + hexstr2bin("d174ab98d277d9f5a5611c2c9f419d9f")), + ok. + +%% +%% +error(Config) when is_list(Config) -> + ?line {'EXIT',{badarg,_}} = (catch erlang:md5(bit_sized_binary(<<"abc">>))), + ?line Ctx0 = erlang:md5_init(), + ?line {'EXIT',{badarg,_}} = + (catch erlang:md5_update(Ctx0, bit_sized_binary(<<"abcfjldjd">>))), + ?line {'EXIT',{badarg,_}} = + (catch erlang:md5_update(Ctx0, ["something",bit_sized_binary(<<"abcfjldjd">>)])), + ?line {'EXIT',{badarg,_}} = + (catch erlang:md5_update(bit_sized_binary(Ctx0), "something")), + ?line {'EXIT',{badarg,_}} = (catch erlang:md5_final(bit_sized_binary(Ctx0))), + ?line m(erlang:md5_final(Ctx0), hexstr2bin("d41d8cd98f00b204e9800998ecf8427e")), + ok. + + +%% +%% +unaligned_context(Config) when is_list(Config) -> + ?line Ctx0 = erlang:md5_init(), + ?line Ctx1 = erlang:md5_update(unaligned_sub_bin(Ctx0), "ABCDEFGHIJKLMNOPQRSTUVWXYZ"), + ?line Ctx = erlang:md5_update(unaligned_sub_bin(Ctx1), + "abcdefghijklmnopqrstuvwxyz0123456789"), + ?line m(erlang:md5_final(unaligned_sub_bin(Ctx)), + hexstr2bin("d174ab98d277d9f5a5611c2c9f419d9f")), + ok. + +%% +%% Help functions +%% + +t_md5_test(Str, ResultStr) -> + ResultBin = hexstr2bin(ResultStr), + m(erlang:md5(Str), ResultBin), + Bin = list_to_binary(Str), + m(erlang:md5(Bin), ResultBin), + UnalignedSubBin = unaligned_sub_bin(Bin), + m(erlang:md5(UnalignedSubBin), ResultBin). + +m(X, X) -> true. + +hexstr2bin(S) -> + list_to_binary(hexstr2list(S)). + +hexstr2list([X,Y|T]) -> + [mkint(X)*16 + mkint(Y) | hexstr2list(T)]; +hexstr2list([]) -> + []. + +mkint(C) when $0 =< C, C =< $9 -> + C - $0; +mkint(C) when $A =< C, C =< $F -> + C - $A + 10; +mkint(C) when $a =< C, C =< $f -> + C - $a + 10. + +unaligned_sub_bin(Bin0) -> + Bin1 = <<0:3,Bin0/binary,31:5>>, + Sz = size(Bin0), + <<0:3,Bin:Sz/binary,31:5>> = id(Bin1), + Bin. + +%% Add 1 bit to the size of the binary. +bit_sized_binary(Bin0) -> + Bin = <<Bin0/binary,1:1>>, + BitSize = bit_size(Bin), + BitSize = 8*size(Bin) + 1, + Bin. + +id(I) -> I. + + diff --git a/erts/emulator/test/crypto_reference.erl b/erts/emulator/test/crypto_reference.erl new file mode 100644 index 0000000000..99107e3b57 --- /dev/null +++ b/erts/emulator/test/crypto_reference.erl @@ -0,0 +1,856 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%% Reference implementations of crc32, adler32 and md5 in erlang. Used +%% by crypto_SUITE. +%% + +-module(crypto_reference). + +-export([adler32/1, crc32/1, md5_init/0, md5_update/2, md5_final/1]). +-export([crc32_table/0, reflect8_table/0]). + +-define(BASE, 65521). +-define(NMAX, 5552). + +-define(AINIT,<<0,0,0,1>>). + +adler32(Bin) when is_binary(Bin) -> + B2 = adler32(Bin,0,1), + <<Sum:32/big>> = B2, + Sum; + +adler32(IoList) -> + adler32(erlang:iolist_to_binary(IoList)). + +adler32(<<>>,B,A) -> + <<B:16/big,A:16/big>>; + +adler32(<<CH:8,T/binary>>,B,A) -> + NewA = (A+CH) rem ?BASE, + NewB = (B+NewA) rem ?BASE, + adler32(T,NewB,NewA). + +-define(FINAL_XOR_VALUE,16#FFFFFFFF). +-define(INITIAL_REMAINDER,16#FFFFFFFF). + +reflect_bin(<<>>,Res) -> + Res; +reflect_bin(<<X:1,Rest/bitstring>>,BS) -> + reflect_bin(Rest,<<X:1,BS/bitstring>>). +reflect(Data,8) -> + reflect8(Data); +reflect(Data,32) -> + <<A:8,B:8,C:8,D:8>> = <<Data:32>>, + ND = reflect8(D), + NC = reflect8(C), + NB = reflect8(B), + NA = reflect8(A), + <<Result:32>> = <<ND:8,NC:8,NB:8,NA:8>>, + Result; +reflect(Data,Size) -> + <<NewData:Size>> = reflect_bin(<<Data:Size>>,<<>>), + NewData. +crc32(<<>>,Remainder) -> + reflect(Remainder,32) bxor ?FINAL_XOR_VALUE; +crc32(<<CH:8,T/binary>>,Remainder) -> + Data = reflect(CH,8) bxor (Remainder bsr 24), + NewRem = crcTab32(Data) bxor ((Remainder bsl 8) band 16#FFFFFFFF), +% io:format("CH = ~p (~p)~n",[CH,reflect(CH,8)]), +% io:format("No reflect = ~p~n",[(CH bxor (Remainder bsr 24))]), +% io:format("Data = ~p, NewRem = ~p~n",[Data,NewRem]), + crc32(T,NewRem). + +crc32(Bin) when is_binary(Bin) -> + crc32(Bin,?INITIAL_REMAINDER); +crc32(L) -> + crc32(erlang:iolist_to_binary(L)). + +bitmod2(0,Remainder,_Topbit,_Polynomial,_Mask) -> + %io:format("~p ",[Remainder]), + Remainder; +bitmod2(N,Remainder,Topbit,Polynomial,Mask) -> + %io:format("~p ",[Remainder]), + case (Remainder band Topbit) of + 0 -> + bitmod2(N-1,(Remainder bsl 1) band Mask,Topbit,Polynomial,Mask); + _ -> + bitmod2(N-1,((Remainder bsl 1) bxor Polynomial) band Mask,Topbit,Polynomial,Mask) + end. + +mask(CrcSize) -> + 16#FFFFFFFF bsr (32 - CrcSize). + +calc_crc_table(256,_CrcSize,_Polynomial) -> + ok; +calc_crc_table(Dividend,CrcSize,Polynomial) -> + Mask = mask(CrcSize), + Remainder = (Dividend bsl (CrcSize - 8)) band Mask, + TopBit = 1 bsl (CrcSize - 1), + Rem2 = bitmod2(8,Remainder,TopBit,Polynomial,Mask), + io:format("crcTab~p(~p) -> ~p;~n",[CrcSize,Dividend,Rem2]), + calc_crc_table(Dividend+1,CrcSize,Polynomial). + +crc32_table() -> + calc_crc_table(0,32,16#04C11DB7). + +reflect8_table(256) -> + ok; +reflect8_table(N) -> + X = reflect(N,8), + io:format("reflect8(~p) -> ~p;~n",[N,X]), + reflect8_table(N+1). +reflect8_table() -> + reflect8_table(0). + +%CRC32 table calculated with crc32_table above +crcTab32(0) -> 0; +crcTab32(1) -> 79764919; +crcTab32(2) -> 159529838; +crcTab32(3) -> 222504665; +crcTab32(4) -> 319059676; +crcTab32(5) -> 398814059; +crcTab32(6) -> 445009330; +crcTab32(7) -> 507990021; +crcTab32(8) -> 638119352; +crcTab32(9) -> 583659535; +crcTab32(10) -> 797628118; +crcTab32(11) -> 726387553; +crcTab32(12) -> 890018660; +crcTab32(13) -> 835552979; +crcTab32(14) -> 1015980042; +crcTab32(15) -> 944750013; +crcTab32(16) -> 1276238704; +crcTab32(17) -> 1221641927; +crcTab32(18) -> 1167319070; +crcTab32(19) -> 1095957929; +crcTab32(20) -> 1595256236; +crcTab32(21) -> 1540665371; +crcTab32(22) -> 1452775106; +crcTab32(23) -> 1381403509; +crcTab32(24) -> 1780037320; +crcTab32(25) -> 1859660671; +crcTab32(26) -> 1671105958; +crcTab32(27) -> 1733955601; +crcTab32(28) -> 2031960084; +crcTab32(29) -> 2111593891; +crcTab32(30) -> 1889500026; +crcTab32(31) -> 1952343757; +crcTab32(32) -> 2552477408; +crcTab32(33) -> 2632100695; +crcTab32(34) -> 2443283854; +crcTab32(35) -> 2506133561; +crcTab32(36) -> 2334638140; +crcTab32(37) -> 2414271883; +crcTab32(38) -> 2191915858; +crcTab32(39) -> 2254759653; +crcTab32(40) -> 3190512472; +crcTab32(41) -> 3135915759; +crcTab32(42) -> 3081330742; +crcTab32(43) -> 3009969537; +crcTab32(44) -> 2905550212; +crcTab32(45) -> 2850959411; +crcTab32(46) -> 2762807018; +crcTab32(47) -> 2691435357; +crcTab32(48) -> 3560074640; +crcTab32(49) -> 3505614887; +crcTab32(50) -> 3719321342; +crcTab32(51) -> 3648080713; +crcTab32(52) -> 3342211916; +crcTab32(53) -> 3287746299; +crcTab32(54) -> 3467911202; +crcTab32(55) -> 3396681109; +crcTab32(56) -> 4063920168; +crcTab32(57) -> 4143685023; +crcTab32(58) -> 4223187782; +crcTab32(59) -> 4286162673; +crcTab32(60) -> 3779000052; +crcTab32(61) -> 3858754371; +crcTab32(62) -> 3904687514; +crcTab32(63) -> 3967668269; +crcTab32(64) -> 881225847; +crcTab32(65) -> 809987520; +crcTab32(66) -> 1023691545; +crcTab32(67) -> 969234094; +crcTab32(68) -> 662832811; +crcTab32(69) -> 591600412; +crcTab32(70) -> 771767749; +crcTab32(71) -> 717299826; +crcTab32(72) -> 311336399; +crcTab32(73) -> 374308984; +crcTab32(74) -> 453813921; +crcTab32(75) -> 533576470; +crcTab32(76) -> 25881363; +crcTab32(77) -> 88864420; +crcTab32(78) -> 134795389; +crcTab32(79) -> 214552010; +crcTab32(80) -> 2023205639; +crcTab32(81) -> 2086057648; +crcTab32(82) -> 1897238633; +crcTab32(83) -> 1976864222; +crcTab32(84) -> 1804852699; +crcTab32(85) -> 1867694188; +crcTab32(86) -> 1645340341; +crcTab32(87) -> 1724971778; +crcTab32(88) -> 1587496639; +crcTab32(89) -> 1516133128; +crcTab32(90) -> 1461550545; +crcTab32(91) -> 1406951526; +crcTab32(92) -> 1302016099; +crcTab32(93) -> 1230646740; +crcTab32(94) -> 1142491917; +crcTab32(95) -> 1087903418; +crcTab32(96) -> 2896545431; +crcTab32(97) -> 2825181984; +crcTab32(98) -> 2770861561; +crcTab32(99) -> 2716262478; +crcTab32(100) -> 3215044683; +crcTab32(101) -> 3143675388; +crcTab32(102) -> 3055782693; +crcTab32(103) -> 3001194130; +crcTab32(104) -> 2326604591; +crcTab32(105) -> 2389456536; +crcTab32(106) -> 2200899649; +crcTab32(107) -> 2280525302; +crcTab32(108) -> 2578013683; +crcTab32(109) -> 2640855108; +crcTab32(110) -> 2418763421; +crcTab32(111) -> 2498394922; +crcTab32(112) -> 3769900519; +crcTab32(113) -> 3832873040; +crcTab32(114) -> 3912640137; +crcTab32(115) -> 3992402750; +crcTab32(116) -> 4088425275; +crcTab32(117) -> 4151408268; +crcTab32(118) -> 4197601365; +crcTab32(119) -> 4277358050; +crcTab32(120) -> 3334271071; +crcTab32(121) -> 3263032808; +crcTab32(122) -> 3476998961; +crcTab32(123) -> 3422541446; +crcTab32(124) -> 3585640067; +crcTab32(125) -> 3514407732; +crcTab32(126) -> 3694837229; +crcTab32(127) -> 3640369242; +crcTab32(128) -> 1762451694; +crcTab32(129) -> 1842216281; +crcTab32(130) -> 1619975040; +crcTab32(131) -> 1682949687; +crcTab32(132) -> 2047383090; +crcTab32(133) -> 2127137669; +crcTab32(134) -> 1938468188; +crcTab32(135) -> 2001449195; +crcTab32(136) -> 1325665622; +crcTab32(137) -> 1271206113; +crcTab32(138) -> 1183200824; +crcTab32(139) -> 1111960463; +crcTab32(140) -> 1543535498; +crcTab32(141) -> 1489069629; +crcTab32(142) -> 1434599652; +crcTab32(143) -> 1363369299; +crcTab32(144) -> 622672798; +crcTab32(145) -> 568075817; +crcTab32(146) -> 748617968; +crcTab32(147) -> 677256519; +crcTab32(148) -> 907627842; +crcTab32(149) -> 853037301; +crcTab32(150) -> 1067152940; +crcTab32(151) -> 995781531; +crcTab32(152) -> 51762726; +crcTab32(153) -> 131386257; +crcTab32(154) -> 177728840; +crcTab32(155) -> 240578815; +crcTab32(156) -> 269590778; +crcTab32(157) -> 349224269; +crcTab32(158) -> 429104020; +crcTab32(159) -> 491947555; +crcTab32(160) -> 4046411278; +crcTab32(161) -> 4126034873; +crcTab32(162) -> 4172115296; +crcTab32(163) -> 4234965207; +crcTab32(164) -> 3794477266; +crcTab32(165) -> 3874110821; +crcTab32(166) -> 3953728444; +crcTab32(167) -> 4016571915; +crcTab32(168) -> 3609705398; +crcTab32(169) -> 3555108353; +crcTab32(170) -> 3735388376; +crcTab32(171) -> 3664026991; +crcTab32(172) -> 3290680682; +crcTab32(173) -> 3236090077; +crcTab32(174) -> 3449943556; +crcTab32(175) -> 3378572211; +crcTab32(176) -> 3174993278; +crcTab32(177) -> 3120533705; +crcTab32(178) -> 3032266256; +crcTab32(179) -> 2961025959; +crcTab32(180) -> 2923101090; +crcTab32(181) -> 2868635157; +crcTab32(182) -> 2813903052; +crcTab32(183) -> 2742672763; +crcTab32(184) -> 2604032198; +crcTab32(185) -> 2683796849; +crcTab32(186) -> 2461293480; +crcTab32(187) -> 2524268063; +crcTab32(188) -> 2284983834; +crcTab32(189) -> 2364738477; +crcTab32(190) -> 2175806836; +crcTab32(191) -> 2238787779; +crcTab32(192) -> 1569362073; +crcTab32(193) -> 1498123566; +crcTab32(194) -> 1409854455; +crcTab32(195) -> 1355396672; +crcTab32(196) -> 1317987909; +crcTab32(197) -> 1246755826; +crcTab32(198) -> 1192025387; +crcTab32(199) -> 1137557660; +crcTab32(200) -> 2072149281; +crcTab32(201) -> 2135122070; +crcTab32(202) -> 1912620623; +crcTab32(203) -> 1992383480; +crcTab32(204) -> 1753615357; +crcTab32(205) -> 1816598090; +crcTab32(206) -> 1627664531; +crcTab32(207) -> 1707420964; +crcTab32(208) -> 295390185; +crcTab32(209) -> 358241886; +crcTab32(210) -> 404320391; +crcTab32(211) -> 483945776; +crcTab32(212) -> 43990325; +crcTab32(213) -> 106832002; +crcTab32(214) -> 186451547; +crcTab32(215) -> 266083308; +crcTab32(216) -> 932423249; +crcTab32(217) -> 861060070; +crcTab32(218) -> 1041341759; +crcTab32(219) -> 986742920; +crcTab32(220) -> 613929101; +crcTab32(221) -> 542559546; +crcTab32(222) -> 756411363; +crcTab32(223) -> 701822548; +crcTab32(224) -> 3316196985; +crcTab32(225) -> 3244833742; +crcTab32(226) -> 3425377559; +crcTab32(227) -> 3370778784; +crcTab32(228) -> 3601682597; +crcTab32(229) -> 3530312978; +crcTab32(230) -> 3744426955; +crcTab32(231) -> 3689838204; +crcTab32(232) -> 3819031489; +crcTab32(233) -> 3881883254; +crcTab32(234) -> 3928223919; +crcTab32(235) -> 4007849240; +crcTab32(236) -> 4037393693; +crcTab32(237) -> 4100235434; +crcTab32(238) -> 4180117107; +crcTab32(239) -> 4259748804; +crcTab32(240) -> 2310601993; +crcTab32(241) -> 2373574846; +crcTab32(242) -> 2151335527; +crcTab32(243) -> 2231098320; +crcTab32(244) -> 2596047829; +crcTab32(245) -> 2659030626; +crcTab32(246) -> 2470359227; +crcTab32(247) -> 2550115596; +crcTab32(248) -> 2947551409; +crcTab32(249) -> 2876312838; +crcTab32(250) -> 2788305887; +crcTab32(251) -> 2733848168; +crcTab32(252) -> 3165939309; +crcTab32(253) -> 3094707162; +crcTab32(254) -> 3040238851; +crcTab32(255) -> 2985771188; +crcTab32(_) -> exit(not_a_byte). + +%% +%% Reflect8 table generated with code above crcTab32 +%% + +reflect8(0) -> 0; +reflect8(1) -> 128; +reflect8(2) -> 64; +reflect8(3) -> 192; +reflect8(4) -> 32; +reflect8(5) -> 160; +reflect8(6) -> 96; +reflect8(7) -> 224; +reflect8(8) -> 16; +reflect8(9) -> 144; +reflect8(10) -> 80; +reflect8(11) -> 208; +reflect8(12) -> 48; +reflect8(13) -> 176; +reflect8(14) -> 112; +reflect8(15) -> 240; +reflect8(16) -> 8; +reflect8(17) -> 136; +reflect8(18) -> 72; +reflect8(19) -> 200; +reflect8(20) -> 40; +reflect8(21) -> 168; +reflect8(22) -> 104; +reflect8(23) -> 232; +reflect8(24) -> 24; +reflect8(25) -> 152; +reflect8(26) -> 88; +reflect8(27) -> 216; +reflect8(28) -> 56; +reflect8(29) -> 184; +reflect8(30) -> 120; +reflect8(31) -> 248; +reflect8(32) -> 4; +reflect8(33) -> 132; +reflect8(34) -> 68; +reflect8(35) -> 196; +reflect8(36) -> 36; +reflect8(37) -> 164; +reflect8(38) -> 100; +reflect8(39) -> 228; +reflect8(40) -> 20; +reflect8(41) -> 148; +reflect8(42) -> 84; +reflect8(43) -> 212; +reflect8(44) -> 52; +reflect8(45) -> 180; +reflect8(46) -> 116; +reflect8(47) -> 244; +reflect8(48) -> 12; +reflect8(49) -> 140; +reflect8(50) -> 76; +reflect8(51) -> 204; +reflect8(52) -> 44; +reflect8(53) -> 172; +reflect8(54) -> 108; +reflect8(55) -> 236; +reflect8(56) -> 28; +reflect8(57) -> 156; +reflect8(58) -> 92; +reflect8(59) -> 220; +reflect8(60) -> 60; +reflect8(61) -> 188; +reflect8(62) -> 124; +reflect8(63) -> 252; +reflect8(64) -> 2; +reflect8(65) -> 130; +reflect8(66) -> 66; +reflect8(67) -> 194; +reflect8(68) -> 34; +reflect8(69) -> 162; +reflect8(70) -> 98; +reflect8(71) -> 226; +reflect8(72) -> 18; +reflect8(73) -> 146; +reflect8(74) -> 82; +reflect8(75) -> 210; +reflect8(76) -> 50; +reflect8(77) -> 178; +reflect8(78) -> 114; +reflect8(79) -> 242; +reflect8(80) -> 10; +reflect8(81) -> 138; +reflect8(82) -> 74; +reflect8(83) -> 202; +reflect8(84) -> 42; +reflect8(85) -> 170; +reflect8(86) -> 106; +reflect8(87) -> 234; +reflect8(88) -> 26; +reflect8(89) -> 154; +reflect8(90) -> 90; +reflect8(91) -> 218; +reflect8(92) -> 58; +reflect8(93) -> 186; +reflect8(94) -> 122; +reflect8(95) -> 250; +reflect8(96) -> 6; +reflect8(97) -> 134; +reflect8(98) -> 70; +reflect8(99) -> 198; +reflect8(100) -> 38; +reflect8(101) -> 166; +reflect8(102) -> 102; +reflect8(103) -> 230; +reflect8(104) -> 22; +reflect8(105) -> 150; +reflect8(106) -> 86; +reflect8(107) -> 214; +reflect8(108) -> 54; +reflect8(109) -> 182; +reflect8(110) -> 118; +reflect8(111) -> 246; +reflect8(112) -> 14; +reflect8(113) -> 142; +reflect8(114) -> 78; +reflect8(115) -> 206; +reflect8(116) -> 46; +reflect8(117) -> 174; +reflect8(118) -> 110; +reflect8(119) -> 238; +reflect8(120) -> 30; +reflect8(121) -> 158; +reflect8(122) -> 94; +reflect8(123) -> 222; +reflect8(124) -> 62; +reflect8(125) -> 190; +reflect8(126) -> 126; +reflect8(127) -> 254; +reflect8(128) -> 1; +reflect8(129) -> 129; +reflect8(130) -> 65; +reflect8(131) -> 193; +reflect8(132) -> 33; +reflect8(133) -> 161; +reflect8(134) -> 97; +reflect8(135) -> 225; +reflect8(136) -> 17; +reflect8(137) -> 145; +reflect8(138) -> 81; +reflect8(139) -> 209; +reflect8(140) -> 49; +reflect8(141) -> 177; +reflect8(142) -> 113; +reflect8(143) -> 241; +reflect8(144) -> 9; +reflect8(145) -> 137; +reflect8(146) -> 73; +reflect8(147) -> 201; +reflect8(148) -> 41; +reflect8(149) -> 169; +reflect8(150) -> 105; +reflect8(151) -> 233; +reflect8(152) -> 25; +reflect8(153) -> 153; +reflect8(154) -> 89; +reflect8(155) -> 217; +reflect8(156) -> 57; +reflect8(157) -> 185; +reflect8(158) -> 121; +reflect8(159) -> 249; +reflect8(160) -> 5; +reflect8(161) -> 133; +reflect8(162) -> 69; +reflect8(163) -> 197; +reflect8(164) -> 37; +reflect8(165) -> 165; +reflect8(166) -> 101; +reflect8(167) -> 229; +reflect8(168) -> 21; +reflect8(169) -> 149; +reflect8(170) -> 85; +reflect8(171) -> 213; +reflect8(172) -> 53; +reflect8(173) -> 181; +reflect8(174) -> 117; +reflect8(175) -> 245; +reflect8(176) -> 13; +reflect8(177) -> 141; +reflect8(178) -> 77; +reflect8(179) -> 205; +reflect8(180) -> 45; +reflect8(181) -> 173; +reflect8(182) -> 109; +reflect8(183) -> 237; +reflect8(184) -> 29; +reflect8(185) -> 157; +reflect8(186) -> 93; +reflect8(187) -> 221; +reflect8(188) -> 61; +reflect8(189) -> 189; +reflect8(190) -> 125; +reflect8(191) -> 253; +reflect8(192) -> 3; +reflect8(193) -> 131; +reflect8(194) -> 67; +reflect8(195) -> 195; +reflect8(196) -> 35; +reflect8(197) -> 163; +reflect8(198) -> 99; +reflect8(199) -> 227; +reflect8(200) -> 19; +reflect8(201) -> 147; +reflect8(202) -> 83; +reflect8(203) -> 211; +reflect8(204) -> 51; +reflect8(205) -> 179; +reflect8(206) -> 115; +reflect8(207) -> 243; +reflect8(208) -> 11; +reflect8(209) -> 139; +reflect8(210) -> 75; +reflect8(211) -> 203; +reflect8(212) -> 43; +reflect8(213) -> 171; +reflect8(214) -> 107; +reflect8(215) -> 235; +reflect8(216) -> 27; +reflect8(217) -> 155; +reflect8(218) -> 91; +reflect8(219) -> 219; +reflect8(220) -> 59; +reflect8(221) -> 187; +reflect8(222) -> 123; +reflect8(223) -> 251; +reflect8(224) -> 7; +reflect8(225) -> 135; +reflect8(226) -> 71; +reflect8(227) -> 199; +reflect8(228) -> 39; +reflect8(229) -> 167; +reflect8(230) -> 103; +reflect8(231) -> 231; +reflect8(232) -> 23; +reflect8(233) -> 151; +reflect8(234) -> 87; +reflect8(235) -> 215; +reflect8(236) -> 55; +reflect8(237) -> 183; +reflect8(238) -> 119; +reflect8(239) -> 247; +reflect8(240) -> 15; +reflect8(241) -> 143; +reflect8(242) -> 79; +reflect8(243) -> 207; +reflect8(244) -> 47; +reflect8(245) -> 175; +reflect8(246) -> 111; +reflect8(247) -> 239; +reflect8(248) -> 31; +reflect8(249) -> 159; +reflect8(250) -> 95; +reflect8(251) -> 223; +reflect8(252) -> 63; +reflect8(253) -> 191; +reflect8(254) -> 127; +reflect8(255) -> 255; +reflect8(_) -> exit(not_a_byte). + +%%% +%%% Old MD5 implementation by Tony, modified to fit testing +%%% + +-record(md5_ctx, + { + state = { 16#67452301, 16#efcdab89, 16#98badcfe, 16#10325476 }, + count = 0, %% number of bits (64 bit) + buffer = <<>> %% input buffer (16 bytes) + }). + +-define(S11, 7). +-define(S12, 12). +-define(S13, 17). +-define(S14, 22). +-define(S21, 5). +-define(S22, 9). +-define(S23, 14). +-define(S24, 20). +-define(S31, 4). +-define(S32, 11). +-define(S33, 16). +-define(S34, 23). +-define(S41, 6). +-define(S42, 10). +-define(S43, 15). +-define(S44, 21). + +%% F, G, H and I are basic MD5 functions. + +-define(F(X, Y, Z), (((X) band (Y)) bor ((bnot (X)) band (Z)))). +-define(G(X, Y, Z), (((X) band (Z)) bor ((Y) band (bnot (Z))))). +-define(H(X, Y, Z), ((X) bxor (Y) bxor (Z))). +-define(I(X, Y, Z), ((Y) bxor ((X) bor (bnot (Z))))). + +-define(U32(X), ((X) band 16#ffffffff)). + +-define(ROTATE_LEFT(X,N), rotate_left(X,N)). + +%% FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +%% Rotation is separate from addition to prevent recomputation. +%% +-define(FF(A, B, C, D, X, S, AC), + ?ROTATE_LEFT(A + ?F((B), (C), (D)) + (X) + (AC),(S)) + (B)). + +-define(GG(A, B, C, D, X, S, AC), + ?ROTATE_LEFT(A + ?G((B), (C), (D)) + (X) + (AC),(S)) + (B)). + +-define( HH(A, B, C, D, X, S, AC), + ?ROTATE_LEFT(A + ?H((B), (C), (D)) + (X) + (AC),(S)) + (B)). + +-define(II(A, B, C, D, X, S, AC), + ?ROTATE_LEFT(A + ?I((B), (C), (D)) + (X) + (AC),(S)) + (B)). + +md5_init() -> + #md5_ctx {}. + +md5_update(CTX, Input) when is_list(Input) -> + md5_update(CTX,iolist_to_binary(Input)); +md5_update(CTX, Input) when is_binary(Input) -> + Buffer = CTX#md5_ctx.buffer, + LenI = size(Input), + Len = LenI + size(Buffer), + md5_update(<<Buffer/binary,Input/binary>>, Len,CTX#md5_ctx.state, + CTX#md5_ctx.count+(LenI bsl 3)). + +%% +%% update state, count reflects number of bytes +%% including bytes in buffer +%% +md5_update(Buf0, Len0, State0, Count) when Len0 >= 64 -> + {Xs,Buf1} = decode(Buf0, 64), + State1 = transform(State0, Xs), + md5_update(Buf1, Len0 - 64, State1, Count); +md5_update(Buf0, _Len0, State0, Count) -> + #md5_ctx { state = State0, count = Count, buffer = Buf0 }. + +%% produce a digest +md5_final(CTX) -> + %% pad out to a length 56 (we later add a count that makes 64) + Count = CTX#md5_ctx.count, %% number of bits + Index = (Count bsr 3) rem 64, %% number of bytes + PadLen = if Index < 56 -> + 56 - Index; + true -> 120 - Index + end, + CTX1 = md5_update(CTX, list_to_binary(padding(PadLen,[]))), + CTX2 = md5_update(CTX1, list_to_binary(encode([?U32(Count), ?U32(Count bsr 32)]))), + list_to_binary(encode(tuple_to_list(CTX2#md5_ctx.state))). + +%% generate padding info to final +padding(0,Acc) -> Acc; +padding(1,Acc) -> [16#80 | Acc]; +padding(N,Acc) -> padding(N-1, [0 | Acc]). + +%% rotate X as 32-bit unsigned left N bits +rotate_left(X, N) -> + ?U32(X bsl N) bor (?U32(X) bsr (32 - N)). + +%% +%% decodes Len number of bytes into 32 bit integers +%% returns {Xs, Tail} +%% +decode(Buf, Len) -> + decode(Buf, Len, []). + +decode(Buf, 0, Acc) -> + {lists:reverse(Acc), Buf}; +decode(<<A:32/little,Buf/binary>>, N, Acc) -> + decode(Buf, N-4, [ A | Acc]). + +%% +%% Encodes input 32-bit ints into byte buffer output. +%% +encode(Xs) -> encode(Xs, []). + +encode([X | Xs], Acc) -> + encode(Xs, [(X bsr 24) band 16#ff, + (X bsr 16) band 16#ff, + (X bsr 8) band 16#ff, + X band 16#ff | Acc]); +encode([], Acc) -> lists:reverse(Acc). + + +transform({A0,B0,C0,D0}, Xs) -> + [X0,X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12,X13,X14,X15] = Xs, + + %% Round 1 + A1 = ?FF (A0, B0, C0, D0, X0, ?S11, 16#d76aa478), + D1 = ?FF (D0, A1, B0, C0, X1, ?S12, 16#e8c7b756), + C1 = ?FF (C0, D1, A1, B0, X2, ?S13, 16#242070db), + B1 = ?FF (B0, C1, D1, A1, X3, ?S14, 16#c1bdceee), + + A2 = ?FF (A1, B1, C1, D1, X4, ?S11, 16#f57c0faf), + D2 = ?FF (D1, A2, B1, C1, X5, ?S12, 16#4787c62a), + C2 = ?FF (C1, D2, A2, B1, X6, ?S13, 16#a8304613), + B2 = ?FF (B1, C2, D2, A2, X7, ?S14, 16#fd469501), + + A3 = ?FF (A2, B2, C2, D2, X8, ?S11, 16#698098d8), + D3 = ?FF (D2, A3, B2, C2, X9, ?S12, 16#8b44f7af), + C3 = ?FF (C2, D3, A3, B2, X10, ?S13, 16#ffff5bb1), + B3 = ?FF (B2, C3, D3, A3, X11, ?S14, 16#895cd7be), + + A4 = ?FF (A3, B3, C3, D3, X12, ?S11, 16#6b901122), + D4 = ?FF (D3, A4, B3, C3, X13, ?S12, 16#fd987193), + C4 = ?FF (C3, D4, A4, B3, X14, ?S13, 16#a679438e), + B4 = ?FF (B3, C4, D4, A4, X15, ?S14, 16#49b40821), + + %% Round 2 + A5 = ?GG (A4, B4, C4, D4, X1, ?S21, 16#f61e2562), + D5 = ?GG (D4, A5, B4, C4, X6, ?S22, 16#c040b340), + C5 = ?GG (C4, D5, A5, B4, X11, ?S23, 16#265e5a51), + B5 = ?GG (B4, C5, D5, A5, X0, ?S24, 16#e9b6c7aa), + + A6 = ?GG (A5, B5, C5, D5, X5, ?S21, 16#d62f105d), + D6 = ?GG (D5, A6, B5, C5, X10, ?S22, 16#2441453), + C6 = ?GG (C5, D6, A6, B5, X15, ?S23, 16#d8a1e681), + B6 = ?GG (B5, C6, D6, A6, X4, ?S24, 16#e7d3fbc8), + + A7 = ?GG (A6, B6, C6, D6, X9, ?S21, 16#21e1cde6), + D7 = ?GG (D6, A7, B6, C6, X14, ?S22, 16#c33707d6), + C7 = ?GG (C6, D7, A7, B6, X3, ?S23, 16#f4d50d87), + B7 = ?GG (B6, C7, D7, A7, X8, ?S24, 16#455a14ed), + + A8 = ?GG (A7, B7, C7, D7, X13, ?S21, 16#a9e3e905), + D8 = ?GG (D7, A8, B7, C7, X2, ?S22, 16#fcefa3f8), + C8 = ?GG (C7, D8, A8, B7, X7, ?S23, 16#676f02d9), + B8 = ?GG (B7, C8, D8, A8, X12, ?S24, 16#8d2a4c8a), + + %% Round 3 + A9 = ?HH (A8, B8, C8, D8, X5, ?S31, 16#fffa3942), + D9 = ?HH (D8, A9, B8, C8, X8, ?S32, 16#8771f681), + C9 = ?HH (C8, D9, A9, B8, X11, ?S33, 16#6d9d6122), + B9 = ?HH (B8, C9, D9, A9, X14, ?S34, 16#fde5380c), + + A10 = ?HH (A9, B9, C9, D9, X1, ?S31, 16#a4beea44), + D10 = ?HH (D9, A10, B9, C9, X4, ?S32, 16#4bdecfa9), + C10 = ?HH (C9, D10, A10, B9, X7, ?S33, 16#f6bb4b60), + B10 = ?HH (B9, C10, D10, A10, X10, ?S34, 16#bebfbc70), + + A11 = ?HH (A10, B10, C10, D10, X13, ?S31, 16#289b7ec6), + D11 = ?HH (D10, A11, B10, C10, X0, ?S32, 16#eaa127fa), + C11 = ?HH (C10, D11, A11, B10, X3, ?S33, 16#d4ef3085), + B11 = ?HH (B10, C11, D11, A11, X6, ?S34, 16#4881d05), + + A12 = ?HH (A11, B11, C11, D11, X9, ?S31, 16#d9d4d039), + D12 = ?HH (D11, A12, B11, C11, X12, ?S32, 16#e6db99e5), + C12 = ?HH (C11, D12, A12, B11, X15, ?S33, 16#1fa27cf8), + B12 = ?HH (B11, C12, D12, A12, X2, ?S34, 16#c4ac5665), + + %% Round 4 + A13 = ?II (A12, B12, C12, D12, X0, ?S41, 16#f4292244), + D13 = ?II (D12, A13, B12, C12, X7, ?S42, 16#432aff97), + C13 = ?II (C12, D13, A13, B12, X14, ?S43, 16#ab9423a7), + B13 = ?II (B12, C13, D13, A13, X5, ?S44, 16#fc93a039), + + A14 = ?II (A13, B13, C13, D13, X12, ?S41, 16#655b59c3), + D14 = ?II (D13, A14, B13, C13, X3, ?S42, 16#8f0ccc92), + C14 = ?II (C13, D14, A14, B13, X10, ?S43, 16#ffeff47d), + B14 = ?II (B13, C14, D14, A14, X1, ?S44, 16#85845dd1), + + A15 = ?II (A14, B14, C14, D14, X8, ?S41, 16#6fa87e4f), + D15 = ?II (D14, A15, B14, C14, X15, ?S42, 16#fe2ce6e0), + C15 = ?II (C14, D15, A15, B14, X6, ?S43, 16#a3014314), + B15 = ?II (B14, C15, D15, A15, X13, ?S44, 16#4e0811a1), + + A16 = ?II (A15, B15, C15, D15, X4, ?S41, 16#f7537e82), + D16 = ?II (D15, A16, B15, C15, X11, ?S42, 16#bd3af235), + C16 = ?II (C15, D16, A16, B15, X2, ?S43, 16#2ad7d2bb), + B16 = ?II (B15, C16, D16, A16, X9, ?S44, 16#eb86d391), + + {?U32(A0+A16), ?U32(B0+B16), ?U32(C0+C16), ?U32(D0+D16)}. + diff --git a/erts/emulator/test/ddll_SUITE.erl b/erts/emulator/test/ddll_SUITE.erl new file mode 100644 index 0000000000..79047d7de5 --- /dev/null +++ b/erts/emulator/test/ddll_SUITE.erl @@ -0,0 +1,1120 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(ddll_SUITE). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Checks if the dynamic driver and linker loader works. +%%% +%%% These tests can only be run installed (outside clearcase). +%%% +%%% XXX In this suite is missing test cases for reference counts +%%% and that drivers are unloaded when their processes die. +%%% (For me to add :-) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +-export([all/1, ddll_test/1, errors/1, + reference_count/1, + kill_port/1, dont_kill_port/1]). +-export([unload_on_process_exit/1, delayed_unload_with_ports/1, + unload_due_to_process_exit/1, + no_unload_due_to_process_exit/1, no_unload_due_to_process_exit_2/1, + unload_reload_thingie/1, unload_reload_thingie_2/1, + unload_reload_thingie_3/1, reload_pending/1, reload_pending_kill/1, + load_fail_init/1, + reload_pending_fail_init/1, + more_error_codes/1, forced_port_killing/1, + no_trap_exit_and_kill_ports/1, + monitor_demonitor/1, monitor_demonitor_load/1, new_interface/1, + lock_driver/1]). + +% Private exports +-export([echo_loader/2, nice_echo_loader/2 ,properties/1, load_and_unload/1]). + +-import(ordsets, [subtract/2]). + +-include("test_server.hrl"). + +all(suite) -> + [ddll_test, errors, + reference_count, + kill_port, + dont_kill_port, + properties, + load_and_unload, + unload_on_process_exit, + delayed_unload_with_ports, + unload_due_to_process_exit, + no_unload_due_to_process_exit, + no_unload_due_to_process_exit_2, + unload_reload_thingie, + unload_reload_thingie_2, + unload_reload_thingie_3, + reload_pending, + load_fail_init, + reload_pending_fail_init, + reload_pending_kill, + more_error_codes, + forced_port_killing, + no_trap_exit_and_kill_ports, + monitor_demonitor, + monitor_demonitor_load, + new_interface, + lock_driver + ]. + +unload_on_process_exit(suite) -> + []; +unload_on_process_exit(doc) -> + ["Check that the driver is unloaded on process exit"]; +unload_on_process_exit(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line false = lists:member("echo_drv",element(2,erl_ddll:loaded_drivers())), + Parent = self(), + ?line Pid = spawn(fun() -> + receive go -> ok end, + erl_ddll:try_load(Path, echo_drv, []), + Parent ! gone, + receive go -> ok end, + erl_ddll:loaded_drivers(), + exit(banan) + end), + ?line Ref = erlang:monitor(process,Pid), + ?line false = lists:member("echo_drv",element(2,erl_ddll:loaded_drivers())), + Pid ! go, + ?line receive + gone -> ok + end, + ?line true = lists:member("echo_drv",element(2,erl_ddll:loaded_drivers())), + Pid ! go, + ?line receive + {'DOWN', Ref, process, Pid, banan} -> + ok + end, + receive after 500 -> ok end, + ?line false = lists:member("echo_drv",element(2,erl_ddll:loaded_drivers())), + ?line test_server:timetrap_cancel(Dog), + ok. + +delayed_unload_with_ports(suite) -> + []; +delayed_unload_with_ports(doc) -> + ["Check that the driver is unloaded when the last port is closed"]; +delayed_unload_with_ports(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line erl_ddll:try_load(Path, echo_drv, []), + ?line erl_ddll:try_load(Path, echo_drv, []), + ?line Port = open_port({spawn, echo_drv}, [eof]), + ?line 1 = erl_ddll:info(echo_drv, port_count), + ?line Port2 = open_port({spawn, echo_drv}, [eof]), + ?line 2 = erl_ddll:info(echo_drv, port_count), + ?line {ok,pending_process} = erl_ddll:try_unload(echo_drv,[{monitor, pending_driver}]), + ?line {ok,pending_driver,Ref} = erl_ddll:try_unload(echo_drv,[{monitor, pending_driver}]), + ?line ok = receive _ -> false after 0 -> ok end, + ?line Port ! {self(), close}, + ?line 1 = erl_ddll:info(echo_drv, port_count), + ?line ok = receive {Port,closed} -> ok after 1000 -> false end, + ?line Port2 ! {self(), close}, + ?line ok = receive {Port2,closed} -> ok after 1000 -> false end, + ?line ok = receive {'DOWN', Ref, driver, echo_drv, unloaded} -> ok after 1000 -> false end, + ?line test_server:timetrap_cancel(Dog), + ok. + +unload_due_to_process_exit(suite) -> + []; +unload_due_to_process_exit(doc) -> + ["Check that the driver with ports is unloaded on process exit"]; +unload_due_to_process_exit(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line Parent = self(), + ?line F3 = fun() -> + Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}), + receive X -> Parent ! {got,X} end + end, + ?line Pid = spawn(fun() -> + receive go -> ok end, + {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []), + spawn(F3), + receive go -> ok end, + _Port = open_port({spawn, echo_drv}, [eof]), + _Port2 = open_port({spawn, echo_drv}, [eof]), + exit(banan) + end), + ?line Ref = erlang:monitor(process,Pid), + Pid ! go, + ?line {ok,Ref2} = receive + R when is_reference(R) -> {ok,R}; + Other -> {error, Other} + after 500 -> {error, timeout} + end, + Pid ! go, + ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end, + ?line ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end, + ?line test_server:timetrap_cancel(Dog), + ok. + +no_unload_due_to_process_exit(suite) -> + []; +no_unload_due_to_process_exit(doc) -> + ["Check that a driver with driver loaded in another process is not unloaded on process exit"]; +no_unload_due_to_process_exit(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line Parent = self(), + ?line F3 = fun() -> + Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}), + receive X -> Parent ! {got,X} end + end, + ?line Pid = spawn(fun() -> + receive go -> ok end, + {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []), + spawn(F3), + receive go -> ok end, + _Port = open_port({spawn, echo_drv}, [eof]), + _Port2 = open_port({spawn, echo_drv}, [eof]), + exit(banan) + end), + ?line Ref = erlang:monitor(process,Pid), + Pid ! go, + ?line {ok,Ref2} = receive + R when is_reference(R) -> {ok,R}; + Other -> {error, Other} + after 500 -> {error, timeout} + end, + ?line {ok, already_loaded} = erl_ddll:try_load(Path, echo_drv, []), + Pid ! go, + ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end, + ?line ok = receive X -> {error, X} after 300 -> ok end, + ?line ok = unload_expect_fast(echo_drv,[]), + ?line ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end, + ?line test_server:timetrap_cancel(Dog), + ok. + +no_unload_due_to_process_exit_2(suite) -> + []; +no_unload_due_to_process_exit_2(doc) -> + ["Check that a driver with open ports in another process is not unloaded on process exit"]; +no_unload_due_to_process_exit_2(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line Parent = self(), + ?line F3 = fun() -> + Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}), + receive X -> Parent ! {got,X} end + end, + ?line Pid = spawn(fun() -> + receive go -> ok end, + {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []), + spawn(F3), + receive go -> ok end, + _Port = open_port({spawn, echo_drv}, [eof]), + _Port2 = open_port({spawn, echo_drv}, [eof]), + exit(banan) + end), + ?line Ref = erlang:monitor(process,Pid), + Pid ! go, + ?line {ok,Ref2} = receive + R when is_reference(R) -> {ok,R}; + Other -> {error, Other} + after 500 -> {error, timeout} + end, + ?line Port = open_port({spawn, echo_drv}, [eof]), + Pid ! go, + ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end, + ?line ok = receive X -> {error, X} after 300 -> ok end, + ?line erlang:port_close(Port), + ?line ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end, + ?line test_server:timetrap_cancel(Dog), + ok. + +unload_reload_thingie(suite) -> + []; +unload_reload_thingie(doc) -> + ["Check delayed unload and reload"]; +unload_reload_thingie(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line Parent = self(), + ?line {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []), + ?line F3 = fun() -> + Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded_only}), + receive X -> Parent ! {got,X} end + end, + ?line Pid = spawn(fun() -> + receive go -> ok end, + _Port = open_port({spawn, echo_drv}, [eof]), + spawn(F3), + receive go -> ok end, + exit(banan) + end), + ?line Ref = erlang:monitor(process,Pid), + Pid ! go, + ?line {ok,Ref2} = receive + R when is_reference(R) -> {ok,R}; + Other -> {error, Other} + after 500 -> {error, timeout} + end, + ?line {ok,pending_driver,Ref3} = erl_ddll:try_unload(echo_drv,[{monitor,pending}]), + ?line Ref4 = erl_ddll:monitor(driver,{echo_drv,loaded}), + ?line ok = receive {'DOWN',Ref4, driver,echo_drv,load_cancelled} -> ok after 1000 -> false end, + ?line {ok,already_loaded} = erl_ddll:try_load(Path, echo_drv, []), + ?line ok = receive {'UP',Ref3, driver,echo_drv,unload_cancelled} -> ok after 1000 -> false end, + ?line Pid ! go, + ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end, + ?line [{Parent,1}] = erl_ddll:info(echo_drv, processes), + ?line 0 = erl_ddll:info(echo_drv, port_count), + ?line ok = unload_expect_fast(echo_drv,[{monitor,pending}]), + ?line ok = receive + {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok + after 300 -> error + end, + ?line ok = receive X -> {error, X} after 300 -> ok end, + ?line test_server:timetrap_cancel(Dog), + ok. + +unload_reload_thingie_2(suite) -> + []; +unload_reload_thingie_2(doc) -> + ["Check delayed unload and reload"]; +unload_reload_thingie_2(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line Parent = self(), + ?line {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []), + ?line F3 = fun() -> + Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded_only}), + receive X -> Parent ! {got,X} end + end, + ?line Pid = spawn(fun() -> + receive go -> ok end, + _Port = open_port({spawn, echo_drv}, [eof]), + spawn(F3), + receive go -> ok end, + exit(banan) + end), + ?line Ref = erlang:monitor(process,Pid), + Pid ! go, + ?line {ok,Ref2} = receive + R when is_reference(R) -> {ok,R}; + Other -> {error, Other} + after 500 -> {error, timeout} + end, + ?line {ok,pending_driver,Ref3} = erl_ddll:try_load(Path,echo_drv,[{monitor,pending_driver},{reload,pending_driver}]), + ?line Ref4 = erl_ddll:monitor(driver,{echo_drv,unloaded}), + ?line Pid ! go, + ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end, + ?line ok = receive {'DOWN',Ref4, driver,echo_drv,unloaded} -> ok after 1000 -> false end, + ?line ok = receive {'UP',Ref3, driver,echo_drv,loaded} -> ok after 1000 -> false end, + ?line [{Parent,1}] = erl_ddll:info(echo_drv, processes), + ?line 0 = erl_ddll:info(echo_drv, port_count), + ?line ok = receive + {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok + after 300 -> error + end, + ?line ok = unload_expect_fast(echo_drv,[{monitor,pending}]), + ?line ok = receive X -> {error, X} after 300 -> ok end, + ?line test_server:timetrap_cancel(Dog), + ok. + +unload_reload_thingie_3(suite) -> + []; +unload_reload_thingie_3(doc) -> + ["Check delayed unload and reload failure"]; +unload_reload_thingie_3(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line Parent = self(), + ?line {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []), + ?line F3 = fun() -> + Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}), + receive X -> Parent ! {got,X} end + end, + ?line Pid = spawn(fun() -> + receive go -> ok end, + _Port = open_port({spawn, echo_drv}, [eof]), + spawn(F3), + receive go -> ok end, + exit(banan) + end), + ?line Ref = erlang:monitor(process,Pid), + Pid ! go, + ?line {ok,Ref2} = receive + R when is_reference(R) -> {ok,R}; + Other -> {error, Other} + after 500 -> {error, timeout} + end, + ?line {ok,pending_driver,Ref3} = erl_ddll:try_load(filename:join([Path,"skrumpf"]),echo_drv,[{monitor,pending_driver},{reload,pending_driver}]), + ?line Ref4 = erl_ddll:monitor(driver,{echo_drv,unloaded}), + ?line Pid ! go, + ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end, + ?line ok = receive + {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok + after 300 -> error + end, + ?line ok = receive {'DOWN',Ref4,driver,echo_drv,unloaded} -> ok after 300 -> false end, + ?line ok = receive + {'DOWN',Ref3, driver,echo_drv,{load_failure,_}} -> ok + after 1000 -> false + end, + ?line {'EXIT',_} = (catch erl_ddll:info(echo_drv, port_count)), + ?line {error, not_loaded} = erl_ddll:try_unload(echo_drv,[{monitor,pending}]), + ?line ok = receive X -> {error, X} after 300 -> ok end, + ?line test_server:timetrap_cancel(Dog), + ok. + +reload_pending(suite) -> []; +reload_pending(doc) -> ["Reload a driver that is pending on a user"]; +reload_pending(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line Parent = self(), + ?line F3 = fun() -> + Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}), + receive X -> Parent ! {got,X} end + end, + ?line Pid = spawn(fun() -> + receive go -> ok end, + {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []), + spawn(F3), + receive go -> ok end, + _Port = open_port({spawn, echo_drv}, [eof]), + _Port2 = open_port({spawn, echo_drv}, [eof]), + Parent ! opened, + receive go -> ok end, + exit(banan) + end), + ?line Ref = erlang:monitor(process,Pid), + Pid ! go, + ?line {ok,Ref2} = receive + R when is_reference(R) -> {ok,R}; + Other -> {error, Other} + after 500 -> {error, timeout} + end, + ?line {ok, already_loaded} = erl_ddll:try_load(Path, echo_drv, []), + ?line Port = open_port({spawn, echo_drv}, [eof]), + Pid ! go, + ?line receive opened -> ok end, + ?line {error, pending_process} = + erl_ddll:try_load(Path, echo_drv, + [{reload,pending_driver}, + {monitor,pending_driver}]), + ?line {ok, pending_process, Ref3} = + erl_ddll:try_load(Path, echo_drv, + [{reload,pending}, + {monitor,pending}]), + ?line ok = receive X -> {error, X} after 300 -> ok end, + Pid ! go, + ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end, + ?line ok = receive Y -> {error, Y} after 300 -> ok end, + ?line erlang:port_close(Port), + ?line ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end, + ?line ok = receive {'UP', Ref3, driver, echo_drv, loaded} -> ok after 300 -> error end, + [{Parent,1}] = erl_ddll:info(echo_drv,processes), + ?line ok = receive Z -> {error, Z} after 300 -> ok end, + ?line test_server:timetrap_cancel(Dog), + ok. + +load_fail_init(suite) -> []; +load_fail_init(doc) -> ["Tests failure in the init in driver struct."]; +load_fail_init(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line PathFailing = ?config(priv_dir, Config), + ?line [_|_] = AllFailInits = filelib:wildcard("echo_drv_fail_init.*",Path), + ?line lists:foreach(fun(Name) -> + Src = filename:join([Path,Name]), + Ext = filename:extension(Name), + Dst =filename:join([PathFailing,"echo_drv"++Ext]), + file:delete(Dst), + {ok,_} = file:copy(Src,Dst) + end, + AllFailInits), + ?line [_|_] = filelib:wildcard("echo_drv.*",PathFailing), + ?line {error, driver_init_failed} = erl_ddll:try_load(PathFailing, + echo_drv, + [{monitor,pending}]), + ?line ok = receive XX -> + {unexpected,XX} + after 300 -> + ok + end, + ?line test_server:timetrap_cancel(Dog), + ok. + + +reload_pending_fail_init(suite) -> []; +reload_pending_fail_init(doc) -> ["Reload a driver that is pending but init fails"]; +reload_pending_fail_init(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line PathFailing = ?config(priv_dir, Config), + ?line [_|_] = AllFailInits = filelib:wildcard("echo_drv_fail_init.*",Path), + ?line lists:foreach(fun(Name) -> + Src = filename:join([Path,Name]), + Ext = filename:extension(Name), + Dst =filename:join([PathFailing,"echo_drv"++Ext]), + file:delete(Dst), + {ok,_} = file:copy(Src,Dst) + end, + AllFailInits), + ?line [_|_] = filelib:wildcard("echo_drv.*",PathFailing), + ?line Parent = self(), + ?line F3 = fun() -> + Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}), + receive X -> Parent ! {got,X} end + end, + ?line Pid = spawn(fun() -> + receive go -> ok end, + {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []), + spawn(F3), + receive go -> ok end, + _Port = open_port({spawn, echo_drv}, [eof]), + _Port2 = open_port({spawn, echo_drv}, [eof]), + Parent ! opened, + receive go -> ok end, + exit(banan) + end), + ?line Ref = erlang:monitor(process,Pid), + Pid ! go, + ?line {ok,Ref2} = receive + R when is_reference(R) -> {ok,R}; + Other -> {error, Other} + after 500 -> {error, timeout} + end, + ?line {ok, already_loaded} = erl_ddll:try_load(Path, echo_drv, []), + ?line Port = open_port({spawn, echo_drv}, [eof]), + Pid ! go, + ?line receive opened -> ok end, + ?line {ok, pending_process, Ref3} = + erl_ddll:try_load(PathFailing, echo_drv, + [{reload,pending}, + {monitor,pending}]), + ?line ok = receive X -> {error, X} after 300 -> ok end, + Pid ! go, + ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end, + ?line ok = receive Y -> {error, Y} after 300 -> ok end, + ?line erlang:port_close(Port), + ?line ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end, + ?line ok = receive {'DOWN', Ref3, driver, echo_drv, {load_failure,driver_init_failed}} -> ok after 300 -> error end, + ?line {'EXIT',{badarg,_}} = (catch erl_ddll:info(echo_drv,processes)), + + ?line ok = receive Z -> {error, Z} after 300 -> ok end, + ?line test_server:timetrap_cancel(Dog), + ok. + +reload_pending_kill(suite) -> []; +reload_pending_kill(doc) -> ["Reload a driver with kill_ports option " + "that is pending on a user"]; +reload_pending_kill(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line OldFlag = process_flag(trap_exit,true), + ?line Path = ?config(data_dir, Config), + ?line Parent = self(), + ?line F3 = fun() -> + Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}), + receive X -> Parent ! {got,X} end + end, + ?line Pid = spawn(fun() -> + process_flag(trap_exit,true), + receive go -> ok end, + {ok, loaded} = erl_ddll:try_load(Path, echo_drv, [{driver_options,[kill_ports]}]), + spawn(F3), + receive go -> ok end, + Port = open_port({spawn, echo_drv}, [eof]), + Port2 = open_port({spawn, echo_drv}, [eof]), + Parent ! opened, + receive go -> ok end, + receive + {'EXIT', Port2, driver_unloaded} -> + Parent ! first_exit + end, + receive + {'EXIT', Port, driver_unloaded} -> + Parent ! second_exit + end, + receive go -> ok end, + exit(banan) + end), + ?line Ref = erlang:monitor(process,Pid), + Pid ! go, + ?line {ok,Ref2} = receive + R when is_reference(R) -> {ok,R}; + Other -> {error, Other} + after 500 -> {error, timeout} + end, + ?line {ok, already_loaded} = erl_ddll:try_load(Path, echo_drv, [{driver_options,[kill_ports]}]), + ?line {error,inconsistent} = erl_ddll:try_load(Path, echo_drv, []), + ?line Port = open_port({spawn, echo_drv}, [eof]), + Pid ! go, + ?line receive opened -> ok end, + ?line {error, pending_process} = + erl_ddll:try_load(Path, echo_drv, + [{driver_options,[kill_ports]}, + {reload,pending_driver}, + {monitor,pending_driver}]), + ?line {ok, pending_process, Ref3} = + erl_ddll:try_load(Path, echo_drv, + [{driver_options,[kill_ports]}, + {reload,pending}, + {monitor,pending}]), + ?line ok = receive + {'EXIT', Port, driver_unloaded} -> + ok + after 300 -> error + end, + Pid ! go, + ?line ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end, + ?line ok = receive {'UP', Ref3, driver, echo_drv, loaded} -> ok after 300 -> error end, + ?line [_,_] = erl_ddll:info(echo_drv,processes), + ?line ok = receive first_exit -> ok after 300 -> error end, + ?line ok = receive second_exit -> ok after 300 -> error end, + ?line 0 = erl_ddll:info(echo_drv,port_count), + ?line ok = receive X -> {error, X} after 300 -> ok end, + Pid ! go, + ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end, + ?line ok = receive Y -> {error, Y} after 300 -> ok end, + ?line Port2 = open_port({spawn, echo_drv}, [eof]), + ?line true = is_port(Port2), + [{Parent,1}] = erl_ddll:info(echo_drv,processes), + ?line 1 = erl_ddll:info(echo_drv,port_count), + ?line erlang:port_close(Port2), + ?line ok = receive {'EXIT', Port2, normal} -> ok after 300 -> error end, + ?line 0 = erl_ddll:info(echo_drv,port_count), + ?line [{Parent,1}] = erl_ddll:info(echo_drv,processes), + ?line Port3 = open_port({spawn, echo_drv}, [eof]), + ?line {ok, pending_driver, Ref4} = + erl_ddll:try_unload(echo_drv,[{monitor,pending_driver}]), + ?line ok = receive + {'EXIT', Port3, driver_unloaded} -> + ok + after 300 -> error + end, + ?line ok = receive {'DOWN', Ref4, driver, echo_drv, unloaded} -> ok after 300 -> error end, + io:format("Port = ~w, Port2 = ~w, Port3 = ~w~n",[Port,Port2,Port3]), + ?line ok = receive Z -> {error, Z} after 300 -> ok end, + ?line process_flag(trap_exit,OldFlag), + ?line test_server:timetrap_cancel(Dog), + ok. + + +more_error_codes(suite) -> + []; +more_error_codes(doc) -> + ["Some more error code checking"]; +more_error_codes(Config) when is_list(Config) -> + ?line {error,Err} = erl_ddll:try_load("./echo_dr",echo_dr,[]), + ?line true = is_list(erl_ddll:format_error(Err)), + ?line true = is_list(erl_ddll:format_error(not_loaded)), + ok. + +forced_port_killing(suite) -> + []; +forced_port_killing(doc) -> + ["Check kill_ports option to try_unload "]; +forced_port_killing(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line OldFlag=process_flag(trap_exit,true), + ?line Parent = self(), + ?line F3 = fun() -> + Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}), + receive X -> Parent ! {got,X} end + end, + ?line {ok, loaded} = erl_ddll:try_load(Path, echo_drv, []), + ?line spawn(F3), + ?line {ok,Ref2} = receive + R when is_reference(R) -> {ok,R}; + Other -> {error, Other} + after 500 -> {error, timeout} + end, + ?line Port = open_port({spawn, echo_drv}, [eof]), + ?line Port2 = open_port({spawn, echo_drv}, [eof]), + ?line {ok, pending_driver, Ref1} = + erl_ddll:try_unload(echo_drv,[{monitor,pending_driver},kill_ports]), + ?line ok = receive + {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok + after 300 -> error + end, + ?line ok = receive {'EXIT',Port,driver_unloaded} -> ok after 300 -> false end, + ?line ok = receive {'EXIT',Port2,driver_unloaded} -> ok after 300 -> false end, + ?line ok = receive {'DOWN',Ref1, driver, echo_drv, unloaded} -> ok after 300 -> false end, + ?line process_flag(trap_exit,OldFlag), + ?line ok = receive X -> {error, X} after 300 -> ok end, + ?line test_server:timetrap_cancel(Dog), + ok. + +no_trap_exit_and_kill_ports(suite) -> + []; +no_trap_exit_and_kill_ports(doc) -> + ["Check delayed unload and reload with no trap_exit"]; +no_trap_exit_and_kill_ports(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line Parent = self(), + ?line OldFlag=process_flag(trap_exit,true), + ?line F3 = fun() -> + Parent ! erl_ddll:monitor(driver,{echo_drv,unloaded}), + receive X -> Parent ! {got,X} end + end, + ?line Pid = spawn(fun() -> + process_flag(trap_exit,false), + receive go -> ok end, + {ok, loaded} = erl_ddll:try_load(Path, echo_drv, + [{driver_options,[kill_ports]}]), + spawn(F3), + receive go -> ok end, + _Port = open_port({spawn, echo_drv}, [eof]), + _Port2 = open_port({spawn, echo_drv}, [eof]), + exit(banan) + end), + ?line Ref = erlang:monitor(process,Pid), + Pid ! go, + ?line {ok,Ref2} = receive + R when is_reference(R) -> {ok,R}; + Other -> {error, Other} + after 500 -> {error, timeout} + end, + ?line {error, inconsistent} = erl_ddll:try_load(Path, echo_drv, []), + ?line MyPort = open_port({spawn, echo_drv}, [eof]), + Pid ! go, + ?line ok = receive {'DOWN', Ref, process, Pid, banan} -> ok after 300 -> error end, + ?line ok = receive {got,{'DOWN', Ref2, driver, echo_drv, unloaded}} -> ok after 300 -> error end, + ?line ok = receive {'EXIT',MyPort,driver_unloaded} -> ok after 300 -> error end, + ?line process_flag(trap_exit,OldFlag), + ?line test_server:timetrap_cancel(Dog), + ok. + +monitor_demonitor(suite) -> + []; +monitor_demonitor(doc) -> + ["Check monitor and demonitor of drivers"]; +monitor_demonitor(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line erl_ddll:try_load(Path, echo_drv, []), + ?line Ref = erl_ddll:monitor(driver,{echo_drv,unloaded}), + ?line Self = self(), + ?line [{Self,1}] = erl_ddll:info(echo_drv,awaiting_unload), + ?line true = erl_ddll:demonitor(Ref), + ?line [] = erl_ddll:info(echo_drv,awaiting_unload), + ?line erl_ddll:try_unload(echo_drv,[]), + ?line ok = receive _ -> error after 300 -> ok end, + ?line test_server:timetrap_cancel(Dog), + ok. + +monitor_demonitor_load(suite) -> + []; +monitor_demonitor_load(doc) -> + ["Check monitor/demonitor of driver loading"]; +monitor_demonitor_load(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line {ok,loaded} = erl_ddll:try_load(Path, echo_drv, []), + ?line Port = open_port({spawn, echo_drv}, [eof]), + ?line Ref = erl_ddll:monitor(driver,{echo_drv,loaded}), + ?line ok = receive {'UP',Ref,driver,echo_drv,loaded} -> ok after 500 -> error end, + ?line {ok, pending_driver} = erl_ddll:try_unload(echo_drv,[]), + ?line Ref2 = erl_ddll:monitor(driver,{echo_drv,loaded}), + ?line ok = receive {'DOWN',Ref2,driver,echo_drv,load_cancelled} -> ok after 0 -> error end, + ?line {ok,already_loaded} = erl_ddll:try_load(Path, echo_drv, []), + ?line {ok, pending_driver} = + erl_ddll:try_load(Path, echo_drv, [{reload,pending_driver}]), + ?line Ref3 = erl_ddll:monitor(driver,{echo_drv,loaded}), + ?line Ref4 = erl_ddll:monitor(driver,{echo_drv,unloaded}), + ?line ok = receive _ -> error after 300 -> ok end, + ?line Self = self(), + ?line [{Self,1}] = erl_ddll:info(echo_drv,awaiting_load), + ?line true = erl_ddll:demonitor(Ref3), + ?line [] = erl_ddll:info(echo_drv,awaiting_load), + ?line erlang:port_close(Port), + ?line ok = receive {'DOWN',Ref4,driver,echo_drv,unloaded} -> ok after 300 -> error end, + ?line ok = receive _ -> error after 300 -> ok end, + ?line ok = unload_expect_fast(echo_drv,[]), + ?line test_server:timetrap_cancel(Dog), + ok. + +new_interface(suite) -> + []; +new_interface(doc) -> + ["Test the new load/unload/reload interface"]; +new_interface(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + % Typical scenario + ?line ok = erl_ddll:load(Path, echo_drv), + ?line Port = open_port({spawn, echo_drv}, [eof]), + ?line ok = erl_ddll:unload(echo_drv), + ?line Port ! {self(), {command, "text"}}, + ?line ok = receive + {Port, {data, "text"}} -> ok; + _ -> error + after + 1000 -> error + end, + ?line Ref = erl_ddll:monitor(driver,{echo_drv,unloaded}), + ?line ok = receive X -> {error, X} after 300 -> ok end, + ?line erlang:port_close(Port), + ?line ok = receive {'DOWN', Ref, driver, echo_drv, unloaded} -> ok after 300 -> error end, + % More than one user + ?line ok = erl_ddll:load(Path, echo_drv), + ?line Ref2 = erl_ddll:monitor(driver,{echo_drv,unloaded}), + ?line ok = erl_ddll:load(Path, echo_drv), + ?line ok = erl_ddll:load(Path, echo_drv), + ?line Port2 = open_port({spawn, echo_drv}, [eof]), + ?line ok = erl_ddll:unload(echo_drv), + ?line Port2 ! {self(), {command, "text"}}, + ?line ok = receive + {Port2, {data, "text"}} -> ok; + _ -> error + after + 1000 -> error + end, + ?line ok = erl_ddll:unload(echo_drv), + ?line Port2 ! {self(), {command, "text"}}, + ?line ok = receive + {Port2, {data, "text"}} -> ok; + _ -> error + after + 1000 -> error + end, + ?line ok = erl_ddll:unload(echo_drv), + ?line Port2 ! {self(), {command, "text"}}, + ?line ok = receive + {Port2, {data, "text"}} -> ok; + _ -> error + after + 1000 -> error + end, + ?line ok = receive X2 -> {error, X2} after 300 -> ok end, + ?line ok = erl_ddll:load(Path, echo_drv), + ?line ok = receive {'UP', Ref2, driver, echo_drv, unload_cancelled} -> ok after 300 -> error end, + ?line Ref3 = erl_ddll:monitor(driver,{echo_drv,unloaded_only}), + ?line erlang:port_close(Port2), + ?line ok = receive X3 -> {error, X3} after 300 -> ok end, + ?line ok = erl_ddll:unload(echo_drv), + ?line ok = receive {'DOWN', Ref3, driver, echo_drv, unloaded} -> ok after 300 -> error end, + ?line test_server:timetrap_cancel(Dog), + ok. + + + + +ddll_test(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + + %?line {error,{already_started,ErlDdllPid}} = erl_ddll:start(), + %?line ErlDdllPid = whereis(ddll_server), + + %% Load the echo driver and verify that it was loaded. + {ok,L1,L2}=load_echo_driver(Path), + + %% Verify that the driver works. + + ?line Port = open_port({spawn, echo_drv}, [eof]), + ?line {hej, "hopp",4711,123445567436543653} = + erlang:port_call(Port,{hej, "hopp",4711,123445567436543653}), + ?line {hej, "hopp",4711,123445567436543653} = + erlang:port_call(Port,47,{hej, "hopp",4711,123445567436543653}), + ?line Port ! {self(), {command, "text"}}, + ?line 1 = receive + {Port, {data, "text"}} -> 1; + _Other -> 2 + after + 1000 -> 2 + end, + ?line Port ! {self(), close}, + ?line receive {Port, closed} -> ok end, + +%% %% Unload the driver and verify that it was unloaded. + ok = unload_echo_driver(L1,L2), + +%% %?line {error, {already_started, _}} = erl_ddll:start(), + + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Tests errors having to do with bad drivers. + +errors(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + + ?line {ok, L1} = erl_ddll:loaded_drivers(), + + ?line {error, {open_error, _}} = erl_ddll:load_driver(Path, bad_name), + ?line {error, driver_init_failed} = erl_ddll:load_driver(Path, initfail_drv), + ?line {error, bad_driver_name} = erl_ddll:load_driver(Path, wrongname_drv), + + %% We assume that there is a statically linked driver named "ddll": + ?line {error, linked_in_driver} = erl_ddll:unload_driver(efile), + ?line {error, not_loaded} = erl_ddll:unload_driver("__pucko_driver__"), + + case os:type() of + {unix, _} -> + ?line {error, no_driver_init} = + erl_ddll:load_driver(Path, noinit_drv); + _ -> + ok + end, + + ?line {ok, L1} = erl_ddll:loaded_drivers(), + + ?line test_server:timetrap_cancel(Dog), + ok. + +reference_count(doc) -> + ["Check that drivers are unloaded when their reference count ", + "reaches zero, and that they cannot be unloaded while ", + "they are still referenced."]; +reference_count(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + + %% Spawn a process that loads the driver (and holds a reference + %% to it). + Pid1=spawn_link(?MODULE, echo_loader, [Path, self()]), + receive + {Pid1, echo_loaded} -> ok + after 2000 -> test_server:fail("echo_loader failed to start.") + end, + + Pid1 ! {self(), die}, + ?line test_server:sleep(200), % Give time to unload. + % Verify that the driver was automaticly unloaded when the + % process died. + ?line {error, not_loaded}=erl_ddll:unload_driver(echo_drv), + + ?line test_server:timetrap_cancel(Dog), + ok. + +% Loads the echo driver, send msg to started, sits and waits to +% get a signal to die, then unloads the driver and terminates. +echo_loader(Path, Starter) -> + ?line {ok, L1, L2}=load_echo_driver(Path), + ?line Starter ! {self(), echo_loaded}, + receive + {Starter, die} -> + ?line unload_echo_driver(L1,L2) + end. + +% Loads the echo driver, send msg to started, sits and waits to +% get a signal to die, then unloads the driver and terminates. +nice_echo_loader(Path, Starter) -> + ?line {ok, L1, L2}=load_nice_echo_driver(Path), + ?line Starter ! {self(), echo_loaded}, + receive + {Starter, die} -> + ?line unload_echo_driver(L1,L2) + end. + + +kill_port(doc) -> + ["Test that a port that uses a driver is killed when the ", + "process that loaded the driver dies."]; +kill_port(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + + %% Spawn a process that loads the driver (and holds a reference + %% to it). + ?line Pid1=spawn(?MODULE, echo_loader, [Path, self()]), + ?line receive + {Pid1, echo_loaded} -> + ok + after 3000 -> + ?line exit(Pid1, kill), + ?line test_server:fail("echo_loader failed to start.") + end, + + % Spawn off a port that uses the driver. + ?line Port = open_port({spawn, echo_drv}, [eof]), + + % Kill the process / unload the driver. + ?line process_flag(trap_exit, true), + ?line exit(Pid1, kill), + ?line test_server:sleep(200), % Give some time to unload. + ?line {error, not_loaded} = erl_ddll:unload_driver(echo_drv), + + % See if the port is killed. + receive + {'EXIT', Port, Reason} -> + io:format("Port exited with reason ~w", [Reason]) + after 5000 -> + ?line test_server:fail("Echo port did not terminate.") + end, + + %% Cleanup and exit. + ?line test_server:timetrap_cancel(Dog), + ok. + +dont_kill_port(doc) -> + ["Test that a port that uses a driver is not killed when the ", + "process that loaded the driver dies and it's nicely opened."]; +dont_kill_port(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + + %% Spawn a process that loads the driver (and holds a reference + %% to it). + ?line Pid1=spawn(?MODULE, nice_echo_loader, [Path, self()]), + ?line receive + {Pid1, echo_loaded} -> + ok + after 3000 -> + ?line exit(Pid1, kill), + ?line test_server:fail("echo_loader failed to start.") + end, + + % Spawn off a port that uses the driver. + ?line Port = open_port({spawn, echo_drv}, [eof]), + + % Kill the process / unload the driver. + ?line process_flag(trap_exit, true), + ?line exit(Pid1, kill), + ?line test_server:sleep(200), % Give some time to unload. + ?line {hej, "hopp",4711,123445567436543653} = + erlang:port_call(Port,{hej, "hopp",4711,123445567436543653}), + ?line [] = erl_ddll:info(echo_drv,processes), + %% unload should work with no owner + ?line ok = erl_ddll:unload_driver(echo_drv), %Kill ports while at it + + % See if the port is killed. + receive + {'EXIT', Port, Reason} -> + io:format("Port exited with reason ~w", [Reason]) + after 5000 -> + ?line test_server:fail("Echo port did not terminate.") + end, + + %% Cleanup and exit. + ?line test_server:timetrap_cancel(Dog), + ok. + +properties(doc) -> ["Test that a process that loaded a driver ", + "is the only process that can unload it."]; +properties(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + + % Let another process load the echo driver. + Pid=spawn_link(?MODULE, echo_loader, [Path, self()]), + receive + {Pid, echo_loaded} -> ok + after 2000 -> test_server:fail("echo_loader failed to start.") + end, + + % Try to unload the driver from this process (the wrong one). + ?line {error, _} = erl_ddll:unload_driver(echo_drv), + ?line {ok, Drivers} = erl_ddll:loaded_drivers(), + ?line case lists:member("echo_drv", Drivers) of + true -> + ok; + false -> + test_server:fail("Unload from wrong process " + "succeeded.") + end, + + % Unload the driver and terminate dummy process. + ?line Pid ! {self(), die}, + ?line test_server:sleep(200), % Give time to unload. + ?line test_server:timetrap_cancel(Dog), + ok. + +load_and_unload(doc) -> ["Load two drivers and unload them in load order."]; +load_and_unload(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(60)), + ?line Path = ?config(data_dir, Config), + ?line {ok, Loaded_drivers1} = erl_ddll:loaded_drivers(), + ?line ok = erl_ddll:load_driver(Path, echo_drv), + ?line ok = erl_ddll:load_driver(Path, dummy_drv), + ?line ok = erl_ddll:unload_driver(echo_drv), + ?line ok = erl_ddll:unload_driver(dummy_drv), + ?line {ok, Loaded_drivers2} = erl_ddll:loaded_drivers(), + ?line Set1 = ordsets:from_list(Loaded_drivers1), + ?line Set2 = ordsets:from_list(Loaded_drivers2), + ?line io:format("~p == ~p\n", [Loaded_drivers1, Loaded_drivers2]), + ?line [] = ordsets:to_list(ordsets:subtract(Set2, Set1)), + + ?line test_server:timetrap_cancel(Dog), + ok. + +lock_driver(suite) -> + []; +lock_driver(doc) -> + ["Check multiple calls to driver_lock_driver"]; +lock_driver(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line {ok, _} = erl_ddll:try_load(Path, lock_drv, []), + ?line Port1 = open_port({spawn, lock_drv}, [eof]), + ?line Port2 = open_port({spawn, lock_drv}, [eof]), + ?line true = erl_ddll:info(lock_drv,permanent), + ?line erlang:port_close(Port1), + ?line erlang:port_close(Port2), + ?line test_server:timetrap_cancel(Dog), + ok. + + +% Load and unload the echo_drv driver. +% Make sure that the driver doesn't exist before we load it, +% and that it exists before we unload it. +load_echo_driver(Path) -> + ?line {ok, L1} = erl_ddll:loaded_drivers(), + ?line ok = erl_ddll:load_driver(Path, echo_drv), + ?line {ok, L2} = erl_ddll:loaded_drivers(), + ?line ["echo_drv"] = ordsets:to_list(subtract(ordsets:from_list(L2), + ordsets:from_list(L1))), + {ok,L1,L2}. + +load_nice_echo_driver(Path) -> + ?line {ok, L1} = erl_ddll:loaded_drivers(), + ?line ok = erl_ddll:load(Path, echo_drv), + ?line {ok, L2} = erl_ddll:loaded_drivers(), + ?line ["echo_drv"] = ordsets:to_list(subtract(ordsets:from_list(L2), + ordsets:from_list(L1))), + {ok,L1,L2}. + +unload_echo_driver(L1,L2) -> + ?line {ok, L2} = erl_ddll:loaded_drivers(), + ?line ok = erl_ddll:unload_driver(echo_drv), + ?line {ok, L3} = erl_ddll:loaded_drivers(), + ?line [] = ordsets:to_list(subtract(ordsets:from_list(L3), + ordsets:from_list(L1))), + ok. + +unload_expect_fast(Driver,XFlags) -> + {ok, pending_driver, Ref} = + erl_ddll:try_unload(Driver, + [{monitor,pending_driver}]++XFlags), + receive + {'DOWN', Ref, driver, Driver, unloaded} -> + case lists:member(atom_to_list(Driver),element(2,erl_ddll:loaded_drivers())) of + true -> + {error, {still_there, Driver}}; + false -> + ok + end + after 1000 -> + {error,{unable_to_unload, Driver}} + end. diff --git a/erts/emulator/test/ddll_SUITE_data/Makefile.src b/erts/emulator/test/ddll_SUITE_data/Makefile.src new file mode 100644 index 0000000000..61652a12e2 --- /dev/null +++ b/erts/emulator/test/ddll_SUITE_data/Makefile.src @@ -0,0 +1,3 @@ +all: echo_drv@dll@ echo_drv_fail_init@dll@ noinit_drv@dll@ wrongname_drv@dll@ initfail_drv@dll@ dummy_drv@dll@ lock_drv@dll@ + +@SHLIB_RULES@ diff --git a/erts/emulator/test/ddll_SUITE_data/dummy_drv.c b/erts/emulator/test/ddll_SUITE_data/dummy_drv.c new file mode 100644 index 0000000000..e0d5067743 --- /dev/null +++ b/erts/emulator/test/ddll_SUITE_data/dummy_drv.c @@ -0,0 +1,49 @@ +#include <stdio.h> +#include "erl_driver.h" + +#ifndef DRIVER_INIT +# define DRIVER_INIT(x) driver_init +#endif + +static ErlDrvPort erlang_port; +static ErlDrvData dummy_start(ErlDrvPort, char*); +static void dummy_read(ErlDrvData port, char *buf, int count); +static void dummy_stop(ErlDrvData), easy_read(ErlDrvData, char*, int); + +static ErlDrvEntry dummy_driver_entry = { + NULL, + dummy_start, + dummy_stop, + dummy_read, + NULL, + NULL, + "dummy_drv", + NULL +}; + +DRIVER_INIT(dummy_drv) +{ + erlang_port = (ErlDrvPort)-1; + return &dummy_driver_entry; +} + +static ErlDrvData dummy_start(ErlDrvPort port,char *buf) +{ + if (erlang_port != (ErlDrvPort)-1) { + return ERL_DRV_ERROR_GENERAL; + } + + erlang_port = port; + return (ErlDrvData)port; +} + +static void dummy_read(ErlDrvData port, char *buf, int count) +{ + driver_output(erlang_port, buf, count); +} + +static void dummy_stop(ErlDrvData port) +{ + erlang_port = (ErlDrvPort)-1; +} + diff --git a/erts/emulator/test/ddll_SUITE_data/echo_drv.c b/erts/emulator/test/ddll_SUITE_data/echo_drv.c new file mode 100644 index 0000000000..edf78a979d --- /dev/null +++ b/erts/emulator/test/ddll_SUITE_data/echo_drv.c @@ -0,0 +1,52 @@ +#include <stdio.h> +#include "erl_driver.h" + +static ErlDrvPort erlang_port; +static ErlDrvData echo_start(ErlDrvPort, char *); +static void from_erlang(ErlDrvData, char*, int); +static int echo_call(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen, unsigned *ret_flags); +static ErlDrvEntry echo_driver_entry = { + NULL, /* Init */ + echo_start, + NULL, /* Stop */ + from_erlang, + NULL, /* Ready input */ + NULL, /* Ready output */ + "echo_drv", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + echo_call +}; + +DRIVER_INIT(echo_drv) +{ + return &echo_driver_entry; +} + +static ErlDrvData +echo_start(ErlDrvPort port, char *buf) +{ + return (ErlDrvData) port; +} + +static void +from_erlang(ErlDrvData data, char *buf, int count) +{ + driver_output((ErlDrvPort) data, buf, count); +} + +static int +echo_call(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen, unsigned *ret_flags) +{ + *rbuf = buf; + *ret_flags |= DRIVER_CALL_KEEP_BUFFER; + return len; +} + diff --git a/erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c b/erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c new file mode 100644 index 0000000000..3b2a44d907 --- /dev/null +++ b/erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c @@ -0,0 +1,59 @@ +#include <stdio.h> +#include "erl_driver.h" + +static ErlDrvPort erlang_port; +static ErlDrvData echo_start(ErlDrvPort, char *); +static void from_erlang(ErlDrvData, char*, int); +static int echo_call(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen, unsigned *ret_flags); +static int echo_failing_init(void); + +static ErlDrvEntry echo_driver_entry = { + echo_failing_init, + echo_start, + NULL, /* Stop */ + from_erlang, + NULL, /* Ready input */ + NULL, /* Ready output */ + "echo_drv", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + echo_call +}; + +DRIVER_INIT(echo_drv) +{ + return &echo_driver_entry; +} + +static int echo_failing_init(void) +{ + return -1; +} + +static ErlDrvData +echo_start(ErlDrvPort port, char *buf) +{ + return (ErlDrvData) port; +} + +static void +from_erlang(ErlDrvData data, char *buf, int count) +{ + driver_output((ErlDrvPort) data, buf, count); +} + +static int +echo_call(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen, unsigned *ret_flags) +{ + *rbuf = buf; + *ret_flags |= DRIVER_CALL_KEEP_BUFFER; + return len; +} + diff --git a/erts/emulator/test/ddll_SUITE_data/initfail_drv.c b/erts/emulator/test/ddll_SUITE_data/initfail_drv.c new file mode 100644 index 0000000000..b676ff5121 --- /dev/null +++ b/erts/emulator/test/ddll_SUITE_data/initfail_drv.c @@ -0,0 +1,46 @@ +#include <stdio.h> +#include "erl_driver.h" + +static ErlDrvPort erlang_port; +static ErlDrvData easy_start(ErlDrvPort, char*); +static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, int); + +static ErlDrvEntry easy_driver_entry = +{ + NULL, + easy_start, + easy_stop, + easy_read, + NULL, + NULL, + "easy", + NULL +}; + +DRIVER_INIT(initfail_drv) +{ + erlang_port = (ErlDrvPort)-1; + return 0; +} + +static ErlDrvData easy_start(ErlDrvPort port, char *buf) +{ + if (erlang_port != (ErlDrvPort)-1) { + return ERL_DRV_ERROR_GENERAL; + } + + fprintf(stderr, "Easy driver started with args %s\n", buf); + erlang_port = port; + return (ErlDrvData)port; +} + +static void easy_read(ErlDrvData port, char *buf, int count) +{ + driver_output(erlang_port, buf, count); +} + +static void easy_stop(ErlDrvData port) +{ + erlang_port = (ErlDrvPort) -1; +} + diff --git a/erts/emulator/test/ddll_SUITE_data/lock_drv.c b/erts/emulator/test/ddll_SUITE_data/lock_drv.c new file mode 100644 index 0000000000..2ec8fa3a29 --- /dev/null +++ b/erts/emulator/test/ddll_SUITE_data/lock_drv.c @@ -0,0 +1,55 @@ +#include <stdio.h> +#include "erl_driver.h" + +static ErlDrvPort erlang_port; +static ErlDrvData echo_start(ErlDrvPort, char *); +static void from_erlang(ErlDrvData, char*, int); +static int echo_call(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen, unsigned *ret_flags); +static ErlDrvEntry echo_driver_entry = { + NULL, /* Init */ + echo_start, + NULL, /* Stop */ + from_erlang, + NULL, /* Ready input */ + NULL, /* Ready output */ + "lock_drv", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + echo_call +}; + +DRIVER_INIT(echo_drv) +{ + return &echo_driver_entry; +} + +static ErlDrvData +echo_start(ErlDrvPort port, char *buf) +{ + driver_lock_driver(port); + return (ErlDrvData) port; +} + +static void +from_erlang(ErlDrvData data, char *buf, int count) +{ + driver_output((ErlDrvPort) data, buf, count); +} + +static int +echo_call(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen, unsigned *ret_flags) +{ + ErlDrvPort port = (ErlDrvPort) drv_data; + driver_lock_driver(port); + *rbuf = buf; + *ret_flags |= DRIVER_CALL_KEEP_BUFFER; + return len; +} + diff --git a/erts/emulator/test/ddll_SUITE_data/noinit_drv.c b/erts/emulator/test/ddll_SUITE_data/noinit_drv.c new file mode 100644 index 0000000000..931386a305 --- /dev/null +++ b/erts/emulator/test/ddll_SUITE_data/noinit_drv.c @@ -0,0 +1,58 @@ +#include <stdio.h> +#include "erl_driver.h" + +static ErlDrvPort erlang_port; +static ErlDrvData easy_start(ErlDrvPort, char*); +static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, int); + +static ErlDrvEntry easy_driver_entry = +{ + NULL, + easy_start, + easy_stop, + easy_read, + NULL, + NULL, + "easy", + NULL +}; + +#ifdef __WIN32__ +/* + * Define a correct driver_init here, or the module won't compile. + * Note that it will not actually be used. + */ +DRIVER_INIT(noinit_drv) + +#else +/* + * Provoke an error when loading the module. + */ +int no_driver_init(void *handle) +#endif +{ + erlang_port = (ErlDrvPort)-1; + return &easy_driver_entry; +} + +static ErlDrvData easy_start(ErlDrvPort port,char *buf) +{ + if (erlang_port != (ErlDrvPort)-1) { + return ERL_DRV_ERROR_GENERAL; + } + + fprintf(stderr, "Easy driver started with args %s\n", buf); + erlang_port = port; + return (ErlDrvData)port; +} + +static void easy_read(ErlDrvData port, char *buf, int count) +{ + driver_output(erlang_port, buf, count); +} + +static void easy_stop(ErlDrvData port) +{ + erlang_port = (ErlDrvPort)-1; +} + diff --git a/erts/emulator/test/ddll_SUITE_data/wrongname_drv.c b/erts/emulator/test/ddll_SUITE_data/wrongname_drv.c new file mode 100644 index 0000000000..3a35820ee7 --- /dev/null +++ b/erts/emulator/test/ddll_SUITE_data/wrongname_drv.c @@ -0,0 +1,50 @@ +#include <stdio.h> +#include "erl_driver.h" + +#ifndef DRIVER_INIT +# define DRIVER_INIT(x) driver_init +#endif + +static ErlDrvPort erlang_port; +static ErlDrvData easy_start(ErlDrvPort, char*); +static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, int); + +static ErlDrvEntry easy_driver_entry = +{ + NULL, + easy_start, + easy_stop, + easy_read, + NULL, + NULL, + "easy", + NULL +}; + +DRIVER_INIT(wrongname_drv) +{ + erlang_port = (ErlDrvPort)-1; + return &easy_driver_entry; +} + +static ErlDrvData easy_start(ErlDrvPort port,char *buf) +{ + if (erlang_port != (ErlDrvPort)-1) { + return ERL_DRV_ERROR_GENERAL; + } + + fprintf(stderr, "Easy driver started with args %s\n", buf); + erlang_port = port; + return (ErlDrvData)port; +} + +static void easy_read(ErlDrvData port, char *buf, int count) +{ + driver_output(erlang_port, buf, count); +} + +static void easy_stop(ErlDrvData port) +{ + erlang_port = (ErlDrvPort)-1; +} + diff --git a/erts/emulator/test/decode_packet_SUITE.erl b/erts/emulator/test/decode_packet_SUITE.erl new file mode 100644 index 0000000000..13f17e972c --- /dev/null +++ b/erts/emulator/test/decode_packet_SUITE.erl @@ -0,0 +1,514 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% Test suite for erlang:decode_packet/3 + +-module(decode_packet_SUITE). + +-include("test_server.hrl"). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + basic/1, packet_size/1, neg/1, http/1, line/1, ssl/1]). + +all(suite) -> + [basic, packet_size, neg, http, line, ssl]. + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Seed = {S1,S2,S3} = now(), + random:seed(S1,S2,S3), + io:format("*** SEED: ~p ***\n", [Seed]), + Dog=?t:timetrap(?t:minutes(1)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +basic(doc) -> []; +basic(suite) -> []; +basic(Config) when is_list(Config) -> + ?line Packet = <<101,22,203,54,175>>, + ?line Rest = <<123,34,0,250>>, + ?line Bin = <<Packet/binary,Rest/binary>>, + ?line {ok, Bin, <<>>} = decode_pkt(raw,Bin), + + ?line {more, 5+1} = decode_pkt(1,<<5,1,2,3,4>>), + ?line {more, 5+2} = decode_pkt(2,<<0,5,1,2,3,4>>), + ?line {more, 5+4} = decode_pkt(4,<<0,0,0,5,1,2,3,4>>), + + ?line {more, undefined} = decode_pkt(1,<<>>), + ?line {more, undefined} = decode_pkt(2,<<0>>), + ?line {more, undefined} = decode_pkt(4,<<0,0,0>>), + + Types = [1,2,4,asn1,sunrm,cdr,fcgi,tpkt,ssl_tls], + + %% Run tests for different header types and bit offsets. + + lists:foreach(fun({Type,Bits})->basic_pack(Type,Packet,Rest,Bits), + more_length(Type,Packet,Bits) end, + [{T,B} || T<-Types, B<-lists:seq(0,32)]), + ok. + +basic_pack(Type,Body,Rest,BitOffs) -> + ?line {Bin,Unpacked,_} = pack(Type,Body,Rest,BitOffs), + ?line {ok, Unpacked, Rest} = decode_pkt(Type,Bin), + case Rest of + <<>> -> ok; + _ -> + ?line <<_:1,NRest/bits>> = Rest, + basic_pack(Type,Body,NRest,BitOffs) + end. + +more_length(Type,Body,BitOffs) -> + ?line {Bin,_,_} = pack(Type,Body,<<>>,BitOffs), + HdrSize = byte_size(Bin) - byte_size(Body), + more_length_do(Type,HdrSize,Bin,byte_size(Bin)). + +more_length_do(_,_,_,0) -> + ok; +more_length_do(Type,HdrSize,Bin,Size) -> + TrySize = (Size*3) div 4, + NSize = if TrySize < HdrSize -> Size - 1; + true -> TrySize + end, + {B1,_} = split_binary(Bin,NSize), + ?line {more, Length} = decode_pkt(Type,B1), + case Length of + L when L=:=byte_size(Bin) -> ok; + undefined when NSize<HdrSize -> ok + end, + more_length_do(Type,HdrSize,Bin,NSize). + + + +pack(Type,Packet,Rest) -> + {Bin,Unpacked} = pack(Type,Packet), + {<<Bin/binary,Rest/bits>>,Unpacked}. + +%pack(0,B,R,Bits) -> +% pack(raw,B,R,Bits); +%pack(raw,Body,Rest,BitOffs) -> +% Orig = <<0:BitOffs,Body/binary,Rest/bits>>, +% <<_:BitOffs,Bin/bits>> = Orig, +% {Bin,<<Bin/binary,Rest/bits>>,Orig}; +pack(Type,Body,Rest,BitOffs) -> + {Packet,Unpacked} = pack(Type,Body), + + %% Make Bin a sub-bin with an arbitrary bitoffset within Orig + Prefix = random:uniform(1 bsl BitOffs) - 1, + Orig = <<Prefix:BitOffs,Packet/binary,Rest/bits>>, + <<_:BitOffs,Bin/bits>> = Orig, + {Bin,Unpacked,Orig}. + +pack(1,Bin) -> + Psz = byte_size(Bin), + {<<Psz:8,Bin/binary>>, Bin}; +pack(2,Bin) -> + Psz = byte_size(Bin), + {<<Psz:16,Bin/binary>>, Bin}; +pack(4,Bin) -> + Psz = byte_size(Bin), + {<<Psz:32,Bin/binary>>, Bin}; +pack(asn1,Bin) -> + Ident = case random:uniform(3) of + 1 -> <<17>>; + 2 -> <<16#1f,16#81,17>>; + 3 -> <<16#1f,16#81,16#80,16#80,17>> + end, + Psz = byte_size(Bin), + Length = case random:uniform(4) of + 1 when Psz < 128 -> + <<Psz:8>>; + R when R=<2 andalso Psz < 16#10000 -> + <<16#82,Psz:16>>; + R when R=<3 andalso Psz < 16#1000000 -> + <<16#83,Psz:24>>; + _ when Psz < 16#100000000 -> + <<16#84,Psz:32>> + end, + Res = <<Ident/binary,Length/binary,Bin/binary>>, + {Res,Res}; +pack(sunrm,Bin) -> + Psz = byte_size(Bin), + Res = if Psz < 16#80000000 -> + <<Psz:32,Bin/binary>> + end, + {Res,Res}; +pack(cdr,Bin) -> + GIOP = <<"GIOP">>, + Major = random:uniform(256) - 1, + Minor = random:uniform(256) - 1, + MType = random:uniform(256) - 1, + Psz = byte_size(Bin), + Res = case random:uniform(2) of + 1 -> <<GIOP/binary,Major:8,Minor:8,0:8,MType:8,Psz:32/big,Bin/binary>>; + 2 -> <<GIOP/binary,Major:8,Minor:8,1:8,MType:8,Psz:32/little,Bin/binary>> + end, + {Res,Res}; +pack(fcgi,Bin) -> + Ver = 1, + Type = random:uniform(256) - 1, + Id = random:uniform(65536) - 1, + PaddSz = random:uniform(16) - 1, + Psz = byte_size(Bin), + Reserv = random:uniform(256) - 1, + Padd = case PaddSz of + 0 -> <<>>; + _ -> list_to_binary([random:uniform(256)-1 + || _<- lists:seq(1,PaddSz)]) + end, + Res = <<Ver:8,Type:8,Id:16,Psz:16/big,PaddSz:8,Reserv:8,Bin/binary>>, + {<<Res/binary,Padd/binary>>, Res}; +pack(tpkt,Bin) -> + Ver = 3, + Reserv = random:uniform(256) - 1, + Size = byte_size(Bin) + 4, + Res = <<Ver:8,Reserv:8,Size:16,Bin/binary>>, + {Res, Res}; +pack(ssl_tls,Bin) -> + Content = case (random:uniform(256) - 1) of + C when C<128 -> C; + _ -> v2hello + end, + Major = random:uniform(256) - 1, + Minor = random:uniform(256) - 1, + pack_ssl(Content,Major,Minor,Bin). + +pack_ssl(Content, Major, Minor, Body) -> + case Content of + v2hello -> + Size = byte_size(Body), + Res = <<1:1,(Size+3):15, 1:8, Major:8, Minor:8, Body/binary>>, + C = 22, + Data = <<1:8, (Size+2):24, Major:8, Minor:8, Body/binary>>; + C when is_integer(C) -> + Size = byte_size(Body), + Res = <<Content:8, Major:8, Minor:8, Size:16, Body/binary>>, + Data = Body + end, + {Res, {ssl_tls,[],C,{Major,Minor}, Data}}. + + +packet_size(doc) -> []; +packet_size(suite) -> []; +packet_size(Config) when is_list(Config) -> + ?line Packet = <<101,22,203,54,175>>, + ?line Rest = <<123,34,0,250>>, + + F = fun({Type,Max})-> + ?line {Bin,Unpacked} = pack(Type,Packet,Rest), + ?line case decode_pkt(Type,Bin,[{packet_size,Max}]) of + {ok,Unpacked,Rest} when Max=:=0; Max>=byte_size(Packet) -> + ok; + {error,_} when Max<byte_size(Packet), Max=/=0 -> + ok; + {error,_} when Type=:=fcgi, Max=/=0 -> + %% packet includes random amount of padding + ok + end + end, + ?line lists:foreach(F, [{T,D} || T<-[1,2,4,asn1,sunrm,cdr,fcgi,tpkt,ssl_tls], + D<-lists:seq(0, byte_size(Packet)*2)]), + + %% Test OTP-8102, "negative" 4-byte sizes. + lists:foreach(fun(Size) -> + ?line {error,_} = decode_pkt(4,<<Size:32,Packet/binary>>) + end, + lists:seq(-10,-1)), + ok. + + +neg(doc) -> []; +neg(suite) -> []; +neg(Config) when is_list(Config) -> + ?line Bin = <<"dummy">>, + Fun = fun()->dummy end, + + BadargF = fun(T,B,Opts)-> {'EXIT',{badarg,_}} = (catch decode_pkt(T,B,Opts)) end, + + %% Invalid Type args + lists:foreach(fun(T)-> BadargF(T,Bin,[]) end, + [3,-1,5,2.0,{2},unknown,[],"line",Bin,Fun,self()]), + + %% Invalid Bin args + lists:foreach(fun(B)-> BadargF(0,B,[]) end, + [3,2.0,unknown,[],"Bin",[Bin],{Bin},Fun,self()]), + + %% Invalid options + InvOpts = [2,false,self(),Bin,"Options",Fun, + packet_size,{packet_size},{packet_size,0,false}, + {packet_size,-1},{packet_size,100.0},{packet_size,false}, + {line_length,-1},{line_length,100.0},{line_length,false}], + + lists:foreach(fun(Opt)-> BadargF(0,Bin,Opt), + BadargF(0,Bin,[Opt]), + BadargF(0,Bin,[Opt,{packet_size,1000}]), + BadargF(0,Bin,[{packet_size,1000},Opt]) end, + InvOpts), + ok. + + +http(doc) -> []; +http(suite) -> []; +http(Config) when is_list(Config) -> + ?line <<"foo">> = http_do(http_request("foo")), + ?line <<" bar">> = http_do(http_request(" bar")), + ?line <<"Hello!">> = http_do(http_response("Hello!")), + + %% Test all known header atoms + Val = "dummy value", + ValB = list_to_binary(Val), + Rest = <<"Rest">>, + HdrF = fun(Str,N) -> + ?line StrA = list_to_atom(Str), + ?line StrB = list_to_binary(Str), + ?line Bin = <<StrB/binary,": ",ValB/binary,"\r\n",Rest/binary>>, + ?line {ok, {http_header,N,StrA,undefined,Val}, Rest} = decode_pkt(httph,Bin), + ?line {ok, {http_header,N,StrA,undefined,ValB}, Rest} = decode_pkt(httph_bin,Bin), + ?line N + 1 + end, + ?line lists:foldl(HdrF, 1, http_hdr_strings()), + + %% Test all known method atoms + MethF = fun(Meth) -> + ?line MethA = list_to_atom(Meth), + ?line MethB = list_to_binary(Meth), + ?line Bin = <<MethB/binary," /invalid/url HTTP/1.0\r\n",Rest/binary>>, + ?line {ok, {http_request,MethA,{abs_path,"/invalid/url"},{1,0}}, + Rest} = decode_pkt(http,Bin), + ?line {ok, {http_request,MethA,{abs_path,<<"/invalid/url">>},{1,0}}, + Rest} = decode_pkt(http_bin,Bin) + end, + ?line lists:foreach(MethF, http_meth_strings()), + + %% Test all uri variants + UriF = fun({Str,ResL,ResB}) -> + Bin = <<"GET ",(list_to_binary(Str))/binary," HTTP/1.1\r\n",Rest/binary>>, + {ok, {http_request, 'GET', ResL, {1,1}}, Rest} = decode_pkt(http,Bin), + {ok, {http_request, 'GET', ResB, {1,1}}, Rest} = decode_pkt(http_bin,Bin) + end, + lists:foreach(UriF, http_uri_variants()), + ok. + +http_with_bin(http) -> + http_bin; +http_with_bin(httph) -> + httph_bin. + +http_do(Tup) -> + http_do(Tup,http). +http_do({Bin, []}, _) -> + Bin; +http_do({Bin,[{_Line,PL,PB}|Tail]}, Type) -> + ?line {ok, PL, Rest} = decode_pkt(Type,Bin), + ?line {ok, PB, Rest} = decode_pkt(http_with_bin(Type),Bin), + + %% Same tests again but as SubBin + PreLen = random:uniform(64), + Prefix = random:uniform(1 bsl PreLen) - 1, + SufLen = random:uniform(64), + Suffix = random:uniform(1 bsl SufLen) - 1, + Orig = <<Prefix:PreLen, Bin/bits, Suffix:SufLen>>, + BinLen = bit_size(Bin), + <<_:PreLen, SubBin:BinLen/bits, _/bits>> = Orig, % Make SubBin + ?line SubBin = Bin, % just to make sure + + ?line {ok, PL, Rest} = decode_pkt(Type,SubBin), + ?line {ok, PB, Rest} = decode_pkt(http_with_bin(Type),SubBin), + http_do({Rest, Tail}, httph). + +http_request(Msg) -> + QnA = [{"POST /invalid/url HTTP/1.1\r\n", + {http_request, 'POST', {abs_path, "/invalid/url" }, {1,1}}, + {http_request, 'POST', {abs_path,<<"/invalid/url">>}, {1,1}}}, + {"Connection: close\r\n", + {http_header,2,'Connection',undefined, "close"}, + {http_header,2,'Connection',undefined,<<"close">>}}, + {"Host\t : localhost:8000\r\n", % white space before : + {http_header,14,'Host',undefined, "localhost:8000"}, + {http_header,14,'Host',undefined,<<"localhost:8000">>}}, + {"User-Agent: perl post\r\n", + {http_header,24,'User-Agent',undefined, "perl post"}, + {http_header,24,'User-Agent',undefined,<<"perl post">>}}, + {"Content-Length: 4\r\n", + {http_header,38,'Content-Length',undefined, "4"}, + {http_header,38,'Content-Length',undefined,<<"4">>}}, + {"Content-Type: text/xml; charset=utf-8\r\n", + {http_header,42,'Content-Type',undefined, "text/xml; charset=utf-8"}, + {http_header,42,'Content-Type',undefined,<<"text/xml; charset=utf-8">>}}, + {"Other-Field: with some text\r\n", + {http_header,0, "Other-Field" ,undefined, "with some text"}, + {http_header,0,<<"Other-Field">>,undefined,<<"with some text">>}}, + {"Multi-Line: Once upon a time in a land far far away,\r\n" + " there lived a princess imprisoned in the highest tower\r\n" + " of the most haunted castle.\r\n", + {http_header,0, "Multi-Line" ,undefined, "Once upon a time in a land far far away,\r\n there lived a princess imprisoned in the highest tower\r\n of the most haunted castle."}, + {http_header,0,<<"Multi-Line">>,undefined,<<"Once upon a time in a land far far away,\r\n there lived a princess imprisoned in the highest tower\r\n of the most haunted castle.">>}}, + {"\r\n", + http_eoh, + http_eoh}], + Bin = lists:foldl(fun({Line,_,_},Acc) -> LineBin = list_to_binary(Line), + <<Acc/binary,LineBin/binary>> end, + <<"">>, QnA), + MsgBin = list_to_binary(Msg), + {<<Bin/binary,MsgBin/binary>>, QnA}. + + +http_response(Msg) -> + QnA = [{"HTTP/1.0 404 Object Not Found\r\n", + {http_response, {1,0}, 404, "Object Not Found"}, + {http_response, {1,0}, 404, <<"Object Not Found">>}}, + {"Server: inets/4.7.16\r\n", + {http_header, 30, 'Server', undefined, "inets/4.7.16"}, + {http_header, 30, 'Server', undefined, <<"inets/4.7.16">>}}, + {"Date: Fri, 04 Jul 2008 17:16:22 GMT\r\n", + {http_header, 3, 'Date', undefined, "Fri, 04 Jul 2008 17:16:22 GMT"}, + {http_header, 3, 'Date', undefined, <<"Fri, 04 Jul 2008 17:16:22 GMT">>}}, + {"Content-Type: text/html\r\n", + {http_header, 42, 'Content-Type', undefined, "text/html"}, + {http_header, 42, 'Content-Type', undefined, <<"text/html">>}}, + {"Content-Length: 207\r\n", + {http_header, 38, 'Content-Length', undefined, "207"}, + {http_header, 38, 'Content-Length', undefined, <<"207">>}}, + {"\r\n", + http_eoh, + http_eoh}], + + + + Bin = lists:foldl(fun({Line,_,_},Acc) -> LineBin = list_to_binary(Line), + <<Acc/binary,LineBin/binary>> end, + <<"">>, QnA), + MsgBin = list_to_binary(Msg), + {<<Bin/binary,MsgBin/binary>>, QnA}. + +http_hdr_strings() -> + %% Must be correct order + ["Cache-Control","Connection","Date","Pragma","Transfer-Encoding", + "Upgrade","Via","Accept", "Accept-Charset", "Accept-Encoding", + "Accept-Language", "Authorization","From","Host","If-Modified-Since", + "If-Match","If-None-Match","If-Range","If-Unmodified-Since","Max-Forwards", + "Proxy-Authorization","Range","Referer","User-Agent","Age","Location", + "Proxy-Authenticate","Public","Retry-After","Server","Vary","Warning", + "Www-Authenticate","Allow","Content-Base","Content-Encoding", + "Content-Language","Content-Length","Content-Location","Content-Md5", + "Content-Range","Content-Type","Etag","Expires","Last-Modified", + "Accept-Ranges","Set-Cookie","Set-Cookie2","X-Forwarded-For","Cookie", + "Keep-Alive","Proxy-Connection"]. + +http_meth_strings() -> + ["OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE"]. + +http_uri_variants() -> + [{"*", '*', '*'}, + {"http://tools.ietf.org/html/rfc3986", + {absoluteURI,http, "tools.ietf.org", undefined, "/html/rfc3986"}, + {absoluteURI,http,<<"tools.ietf.org">>,undefined,<<"/html/rfc3986">>}}, + {"http://otp.ericsson.se:8000/product/internal/", + {absoluteURI,http, "otp.ericsson.se" ,8000, "/product/internal/"}, + {absoluteURI,http,<<"otp.ericsson.se">>,8000,<<"/product/internal/">>}}, + {"https://example.com:8042/over/there?name=ferret#nose", + {absoluteURI,https, "example.com", 8042, "/over/there?name=ferret#nose"}, + {absoluteURI,https,<<"example.com">>,8042,<<"/over/there?name=ferret#nose">>}}, + {"ftp://cnn.example.com&[email protected]/top_story.htm", + {scheme, "ftp", "//cnn.example.com&[email protected]/top_story.htm"}, + {scheme,<<"ftp">>,<<"//cnn.example.com&[email protected]/top_story.htm">>}}, + {"/some/absolute/path", + {abs_path, "/some/absolute/path"}, + {abs_path,<<"/some/absolute/path">>}}, + {"something_else", "something_else", <<"something_else">>}]. + + +line(doc) -> []; +line(suite) -> []; +line(Config) when is_list(Config) -> + Text = <<"POST /invalid/url HTTP/1.1\r\n" + "Connection: close\r\n" + "Host\t : localhost:8000\r\n" + "User-Agent: perl post\r\n" + "Content-Length: 4\r\n" + "Content-Type: text/xml; charset=utf-8\r\n" + "Other-Field: with some text\r\n" + "Multi-Line: Once upon a time in a land far far away,\r\n" + " there lived a princess imprisoned in the highest tower\r\n" + " of the most haunted castle.\r\n" + "\r\nThe residue">>, + + lists:foreach(fun(MaxLen) -> line_do(Text,MaxLen) end, + [0,7,19,29,37]), + ok. + +line_do(Bin,MaxLen) -> + Res = decode_pkt(line,Bin,[{line_length,MaxLen}]), + MyRes = decode_line(Bin,MaxLen), + ?line MyRes = Res, + case Res of + {ok,_,Rest} -> + line_do(Rest,MaxLen); + {more,undefined} -> + ok + end. + +% Emulates decode_packet(line,Bin,[{line_length,MaxLen}]) +decode_line(Bin,MaxLen) -> + ?line case find_in_binary($\n,Bin) of + notfound when MaxLen>0 andalso byte_size(Bin) >= MaxLen -> + {LineB,Rest} = split_binary(Bin,MaxLen), + {ok,LineB,Rest}; + notfound -> + {more,undefined}; + Pos when MaxLen>0 andalso Pos > MaxLen -> + {LineB,Rest} = split_binary(Bin,MaxLen), + {ok,LineB,Rest}; + Pos -> + {LineB,Rest} = split_binary(Bin,Pos), + {ok,LineB,Rest} + end. + +find_in_binary(Byte, Bin) -> + case string:chr(binary_to_list(Bin),Byte) of + 0 -> notfound; + P -> P + end. + +ssl(doc) -> []; +ssl(suite) -> []; +ssl(Config) when is_list(Config) -> + Major = 34, + Minor = 17, + Body = <<234,189,73,199,1,32,4,0,254>>, + Rest = <<23,123,203,12,234>>, + + F = fun(Content) -> + {Packet,Unpacked} = pack_ssl(Content, Major, Minor, Body), + Bin = <<Packet/binary,Rest/binary>>, + ?line {ok, Unpacked, Rest} = decode_pkt(ssl_tls, Bin) + end, + F(25), + F(v2hello), + ok. + +decode_pkt(Type,Bin) -> + decode_pkt(Type,Bin,[]). +decode_pkt(Type,Bin,Opts) -> + %%io:format("decode_packet(~p,~p,~p)\n",[Type,Bin,Opts]), + Res = erlang:decode_packet(Type,Bin,Opts), + %%io:format(" -> ~p\n",[Res]), + Res. + diff --git a/erts/emulator/test/dgawd_handler.erl b/erts/emulator/test/dgawd_handler.erl new file mode 100644 index 0000000000..881354b9da --- /dev/null +++ b/erts/emulator/test/dgawd_handler.erl @@ -0,0 +1,118 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%%------------------------------------------------------------------- +%%% File : dgawd_handler.erl +%%% Author : Rickard Green <[email protected]> +%%% Description : Find out if Driver Gone Away Without Deselecting +%%% have been reported. +%%% +%%% Created : 13 Sep 2006 by Rickard Green <[email protected]> +%%%------------------------------------------------------------------- +-module(dgawd_handler). +-behaviour(gen_event). + +%% API +-export([install/0, restore/0]). +-export([got_dgawd_report/0]). + +%% gen_event callbacks +-export([init/1, handle_event/2, handle_call/2, + handle_info/2, terminate/2, code_change/3]). + +%%==================================================================== +%% API +%%==================================================================== + +install() -> + gen_event:add_handler(error_logger, ?MODULE, []). + +restore() -> + gen_event:delete_handler(error_logger, ?MODULE, []). + +got_dgawd_report() -> + gen_event:call(error_logger, ?MODULE, got_dgawd_report, 10*60*1000). + +%%==================================================================== +%% gen_event callbacks +%%==================================================================== + +init([]) -> + {ok, false}. + +handle_event(_, true) -> + {ok, true}; +handle_event({_, _, {emulator, _,IOList}}, false) -> + {ok, dgawd(lists:flatten(IOList))}; +handle_event(_, State) -> + {ok, State}. + +handle_call(got_dgawd_report, State) -> + {ok, State, State}; +handle_call(_Query, _State) -> + {error, bad_query}. + +handle_info(_, State) -> + {ok, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%% +%% Internal functions +%% + +dgawd([]) -> + false; +dgawd([$d,$r,$i,$v,$e,$r|Cs]) -> + gawd(Cs); +dgawd([_|Cs]) -> + dgawd(Cs). + +gawd([]) -> + false; +gawd([$g,$o,$n,$e|Cs]) -> + awd(Cs); +gawd([_|Cs]) -> + gawd(Cs). + +awd([]) -> + false; +awd([$a,$w,$a,$y|Cs]) -> + wd(Cs); +awd([_|Cs]) -> + awd(Cs). + +wd([]) -> + false; +wd([$w,$i,$t,$h,$o,$u,$t|Cs]) -> + d(Cs); +wd([_|Cs]) -> + wd(Cs). + + +d([]) -> + false; +d([$d,$e,$s,$e,$l,$e,$c,$t,$i,$n,$g|_Cs]) -> + true; +d([_|Cs]) -> + d(Cs). diff --git a/erts/emulator/test/dist_init_unix_SUITE_data/hosts.dn_sp b/erts/emulator/test/dist_init_unix_SUITE_data/hosts.dn_sp new file mode 100644 index 0000000000..6cc288e524 --- /dev/null +++ b/erts/emulator/test/dist_init_unix_SUITE_data/hosts.dn_sp @@ -0,0 +1,7 @@ +# +# Internet host table +# +127.0.0.1 localhost +150.236.20.72 elrond +150.236.20.16 gandalf +150.236.20.99 gandalfina diff --git a/erts/emulator/test/dist_init_unix_SUITE_data/hosts.underscore b/erts/emulator/test/dist_init_unix_SUITE_data/hosts.underscore new file mode 100644 index 0000000000..2e7831ff02 --- /dev/null +++ b/erts/emulator/test/dist_init_unix_SUITE_data/hosts.underscore @@ -0,0 +1,7 @@ +# +# Internet host table +# +127.0.0.1 localhost +150.236.20.72 elrond loghost +150.236.20.16 gandalf +150.236.20.199 under_score diff --git a/erts/emulator/test/dist_init_unix_SUITE_data/nsswitch.conf.dn_sp b/erts/emulator/test/dist_init_unix_SUITE_data/nsswitch.conf.dn_sp new file mode 100644 index 0000000000..55a4f9ac86 --- /dev/null +++ b/erts/emulator/test/dist_init_unix_SUITE_data/nsswitch.conf.dn_sp @@ -0,0 +1,31 @@ +# +# /etc/nsswitch.nis: +# +# An example file that could be copied over to /etc/nsswitch.conf; it +# uses NIS (YP) in conjunction with files. +# +# "hosts:" and "services:" in this file are used only if the +# /etc/netconfig file has a "-" for nametoaddr_libs of "inet" transports. + +# the following two lines obviate the "+" entry in /etc/passwd and /etc/group. +passwd: files nis +group: files nis + +# consult /etc "files" only if nis is down. +hosts: nis [NOTFOUND=return] +networks: nis [NOTFOUND=return] files +protocols: nis [NOTFOUND=return] files +rpc: nis [NOTFOUND=return] files +ethers: nis [NOTFOUND=return] files +netmasks: nis [NOTFOUND=return] files +bootparams: nis [NOTFOUND=return] files +publickey: nis [NOTFOUND=return] files + +netgroup: nis + +automount: files nis +aliases: files nis + +# for efficient getservbyname() avoid nis +services: files nis +sendmailvars: files diff --git a/erts/emulator/test/dist_init_unix_SUITE_data/resolv.conf.dn_sp b/erts/emulator/test/dist_init_unix_SUITE_data/resolv.conf.dn_sp new file mode 100644 index 0000000000..13a78d5bbb --- /dev/null +++ b/erts/emulator/test/dist_init_unix_SUITE_data/resolv.conf.dn_sp @@ -0,0 +1,6 @@ +domain du.etx.ericsson.se +nameserver 150.236.14.16 +nameserver 150.236.16.2 +nameserver 130.100.128.25 +search du.etx.ericsson.se etx.ericsson.se ericsson.se +lookup yp bind file diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl new file mode 100644 index 0000000000..8f48d8a992 --- /dev/null +++ b/erts/emulator/test/distribution_SUITE.erl @@ -0,0 +1,1842 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(distribution_SUITE). + +%% Tests distribution and the tcp driver. + +-include("test_server.hrl"). + +-export([all/1, + ping/1, bulk_send/1, bulk_send_small/1, + bulk_send_big/1, + local_send/1, local_send_small/1, local_send_big/1, + local_send_legal/1, link_to_busy/1, exit_to_busy/1, + lost_exit/1, link_to_dead/1, link_to_dead_new_node/1, + applied_monitor_node/1, ref_port_roundtrip/1, nil_roundtrip/1, + trap_bif/1, trap_bif_1/1, trap_bif_2/1, trap_bif_3/1, + stop_dist/1, dist_auto_connect/1, + dist_auto_connect_never/1, dist_auto_connect_once/1, + dist_parallel_send/1, + atom_roundtrip/1, + atom_roundtrip_r12b/1, + contended_atom_cache_entry/1, + bad_dist_ext/1, + bad_dist_ext_receive/1, + bad_dist_ext_process_info/1, + bad_dist_ext_control/1, + bad_dist_ext_connection_id/1]). + +-export([init_per_testcase/2, fin_per_testcase/2]). + +%% Internal exports. +-export([sender/3, receiver2/2, dummy_waiter/0, dead_process/0, + roundtrip/1, bounce/1, do_dist_auto_connect/1, inet_rpc_server/1, + dist_parallel_sender/3, dist_parallel_receiver/0, + dist_evil_parallel_receiver/0]). + +all(suite) -> [ + ping, bulk_send, local_send, link_to_busy, exit_to_busy, + lost_exit, link_to_dead, link_to_dead_new_node, + applied_monitor_node, ref_port_roundtrip, nil_roundtrip, + stop_dist, trap_bif, dist_auto_connect, dist_parallel_send, + atom_roundtrip, atom_roundtrip_r12b, + contended_atom_cache_entry, + bad_dist_ext + ]. + +-define(DEFAULT_TIMETRAP, 4*60*1000). + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog=?t:timetrap(?DEFAULT_TIMETRAP), + [{watchdog, Dog},{testcase, Func}|Config]. + +fin_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +%%% Don't be too hard on vxworks, the cross server gets nodedown +%%% cause the card is too busy if we don't sleep a little between pings. +sleep() -> + case os:type() of + vxworks -> + receive + after 10 -> + ok + end; + _ -> + ok + end. + +ping(doc) -> + ["Tests pinging a node in different ways."]; +ping(Config) when is_list(Config) -> + Times = 1024, + + %% Ping a non-existing node many times. This used to crash the emulator + %% on Windows. + + ?line Host = hostname(), + ?line BadName = list_to_atom("__pucko__@" ++ Host), + ?line io:format("Pinging ~s (assumed to not exist)", [BadName]), + ?line test_server:do_times(Times, + fun() -> pang = net_adm:ping(BadName), + sleep() + end), + + %% Pings another node. + + ?line {ok, OtherNode} = start_node(distribution_SUITE_other), + ?line io:format("Pinging ~s (assumed to exist)", [OtherNode]), + ?line test_server:do_times(Times, fun() -> pong = net_adm:ping(OtherNode),sleep() end), + ?line stop_node(OtherNode), + + %% Pings our own node many times. + + ?line Node = node(), + ?line io:format("Pinging ~s (the same node)", [Node]), + ?line test_server:do_times(Times, fun() -> pong = net_adm:ping(Node),sleep() end), + + ok. + +bulk_send(doc) -> + ["Tests sending large amount of data to another node and measure", + "the time. This tests that a process that is suspended on a ", + "busy port will eventually be resumed."]; +bulk_send(suite) -> + [bulk_send_small, bulk_send_big]. + +bulk_send_small(Config) when is_list(Config) -> + ?line bulk_send(64, 32). + +bulk_send_big(Config) when is_list(Config) -> + ?line bulk_send(32, 64). + +bulk_send(Terms, BinSize) -> + ?line Dog = test_server:timetrap(test_server:seconds(30)), + + ?line io:format("Sending ~w binaries, each of size ~w K", + [Terms, BinSize]), + ?line {ok, Node} = start_node(bulk_receiver), + ?line Recv = spawn(Node, erlang, apply, [fun receiver/2, [0, 0]]), + ?line Bin = list_to_binary(lists:duplicate(BinSize*1024, 253)), + ?line Size = Terms*size(Bin), + ?line {Elapsed, {Terms, Size}} = test_server:timecall(?MODULE, sender, + [Recv, Bin, Terms]), + ?line stop_node(Node), + + ?line test_server:timetrap_cancel(Dog), + {comment, integer_to_list(trunc(Size/1024/Elapsed+0.5)) ++ " K/s"}. + +sender(To, _Bin, 0) -> + To ! {done, self()}, + receive + Any -> + Any + end; +sender(To, Bin, Left) -> + To ! {term, Bin}, + sender(To, Bin, Left-1). + +%% Receiver process to be run on a slave node. + +receiver(Terms, Size) -> + receive + {term, Bin} -> + receiver(Terms+1, Size+size(Bin)); + {done, ReplyTo} -> + ReplyTo ! {Terms, Size} + end. + + +local_send(suite) -> + [local_send_small, local_send_big, local_send_legal]; +local_send(doc) -> + ["Tests sending small and big messages to a non-existing ", + "local registered process."]. + +local_send_big(doc) -> + ["Sends several big message to an non-registered process on ", + "the local node."]; +local_send_big(Config) when is_list(Config) -> + Data0=local_send_big(doc)++local_send(doc), + Data1=[Data0,[Data0, Data0, [Data0], Data0],Data0], + Data2=Data0++lists:flatten(Data1)++ + list_to_binary(lists:flatten(Data1)), + Func=fun() -> Data2= {arbitrary_name, node()} ! Data2 end, + ?line test_server:do_times(4096, Func), + ok. + +local_send_small(doc) -> + ["Sends a small message to an non-registered process on the ", + "local node."]; +local_send_small(Config) when is_list(Config) -> + Data={some_stupid, "arbitrary", 'Data'}, + Func=fun() -> Data= {unregistered_name, node()} ! Data end, + ?line test_server:do_times(4096, Func), + ok. + +local_send_legal(doc) -> + ["Sends data to a registered process on the local node, ", + "as if it was on another node."]; +local_send_legal(Config) when is_list(Config) -> + Times=16384, + Data={local_send_legal(doc), local_send_legal(doc)}, + Pid=spawn(?MODULE,receiver2, [0, 0]) , + ?line true=register(registered_process, Pid), + + Func=fun() -> Data={registered_process, node()} ! Data end, + TotalSize=size(Data)*Times, + ?line test_server:do_times(Times, Func), + + % Check that all msgs really came through. + Me=self(), + ?line {done, Me}= + {registered_process, node()} ! {done, Me}, + receive + {Times, TotalSize} -> + ok; + _ -> + test_server:fail("Wrong number of msgs received.") + end, + ok. + +receiver2(Num, TotSize) -> + receive + {done, ReplyTo} -> + ReplyTo ! {Num, TotSize}; + Stuff -> + receiver2(Num+1, TotSize+size(Stuff)) + end. + +link_to_busy(doc) -> "Test that link/1 to a busy distribution port works."; +link_to_busy(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(30)), + ?line {ok, Node} = start_node(link_to_busy), + ?line Recv = spawn(Node, erlang, apply, [fun sink/1, [link_to_busy_sink]]), + + Tracer = case os:getenv("TRACE_BUSY_DIST_PORT") of + "true" -> start_busy_dist_port_tracer(); + _ -> false + end, + + %% We will spawn off a process which will try to link to the other + %% node. The linker process will not actually run until this + %% process is suspended due to the busy distribution port (because + %% of the big send). When the link/1 is run, the linker + %% process will block, too, because of the because busy port, + %% and will later be restarted. + + ?line do_busy_test(Node, fun () -> linker(Recv) end), + + %% Same thing, but we apply link/1 instead of calling it directly. + + ?line do_busy_test(Node, fun () -> applied_linker(Recv) end), + + %% Same thing again, but we apply link/1 in the tail of a function. + + ?line do_busy_test(Node, fun () -> tail_applied_linker(Recv) end), + + %% Done. + ?line stop_node(Node), + ?line stop_busy_dist_port_tracer(Tracer), + ?line test_server:timetrap_cancel(Dog), + ok. + +linker(Pid) -> + true = link(Pid), + {links, Links} = process_info(self(), links), + true = lists:member(Pid, Links). + +applied_linker(Pid) -> + true = apply(erlang, link, [Pid]), + {links, Links} = process_info(self(), links), + true = lists:member(Pid, Links). + +tail_applied_linker(Pid) -> + apply(erlang, link, [Pid]). + +exit_to_busy(doc) -> "Test that exit/2 to a busy distribution port works."; +exit_to_busy(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(30)), + ?line {ok, Node} = start_node(exit_to_busy), + + Tracer = case os:getenv("TRACE_BUSY_DIST_PORT") of + "true" -> start_busy_dist_port_tracer(); + _ -> false + end, + + %% We will spawn off a process which will try to exit a process on + %% the other node. That process will not actually run until this + %% process is suspended due to the busy distribution port + %% The process executing exit/2 will block, + %% too, because of the busy distribution port, and will be allowed + %% to continue when the port becomes non-busy. + + ?line Recv1 = spawn(Node, fun () -> sink(exit_to_busy_sink) end), + ?line M1 = erlang:monitor(process, Recv1), + ?line do_busy_test(Node, fun () -> joey_killer(Recv1) end), + ?line receive + {'DOWN', M1, process, Recv1, R1} -> + ?line joey_said_die = R1 + end, + + %% Same thing, but tail call to exit/2. + ?line Recv2 = spawn(Node, fun () -> sink(exit_to_busy_sink) end), + ?line M2 = erlang:monitor(process, Recv2), + ?line do_busy_test(Node, fun () -> tail_joey_killer(Recv2) end), + ?line receive + {'DOWN', M2, process, Recv2, R2} -> + ?line joey_said_die = R2 + end, + + %% Same thing, but we apply exit/2 instead of calling it directly. + ?line Recv3 = spawn(Node, fun () -> sink(exit_to_busy_sink) end), + ?line M3 = erlang:monitor(process, Recv3), + ?line do_busy_test(Node, fun () -> applied_joey_killer(Recv3) end), + ?line receive + {'DOWN', M3, process, Recv3, R3} -> + ?line joey_said_die = R3 + end, + + %% Same thing again, but we apply exit/2 in the tail of a function. + ?line Recv4 = spawn(Node, fun () -> sink(exit_to_busy_sink) end), + ?line M4 = erlang:monitor(process, Recv4), + ?line do_busy_test(Node, fun () -> tail_applied_joey_killer(Recv4) end), + ?line receive + {'DOWN', M4, process, Recv4, R4} -> + ?line joey_said_die = R4 + end, + + %% Done. + ?line stop_node(Node), + ?line stop_busy_dist_port_tracer(Tracer), + ?line test_server:timetrap_cancel(Dog), + ok. + +make_busy_data() -> + Size = 1024*1024, + Key = '__busy__port__data__', + case get(Key) of + undefined -> + Data = list_to_binary(lists:duplicate(Size, 253)), + put(Key, Data), + Data; + Data -> + true = is_binary(Data), + true = size(Data) == Size, + Data + end. + +make_busy(Node, Time) when is_integer(Time) -> + Own = 500, + freeze_node(Node, Time+Own), + Data = make_busy_data(), + %% first make port busy + Pid = spawn_link(fun () -> + forever(fun () -> + dport_reg_send(Node, + '__noone__', + Data) + end) + end), + receive after Own -> ok end, + until(fun () -> + case process_info(Pid, status) of + {status, suspended} -> true; + _ -> false + end + end), + %% then dist entry + make_busy(Node, [nosuspend], Data), + Pid. + +make_busy(Node, Opts, Data) -> + case erlang:send({'__noone__', Node}, Data, Opts) of + nosuspend -> nosuspend; + _ -> make_busy(Node, Opts, Data) + end. + +unmake_busy(Pid) -> + unlink(Pid), + exit(Pid, bang). + +do_busy_test(Node, Fun) -> + Busy = make_busy(Node, 1000), + {P, M} = spawn_monitor(Fun), + receive after 100 -> ok end, + Pinfo = process_info(P, [status, current_function]), + unmake_busy(Busy), + ?t:format("~p : ~p~n", [P, Pinfo]), + case Pinfo of + undefined -> + receive + {'DOWN', M, process, P, Reason} -> + ?t:format("~p died with exit reason ~p~n", [P, Reason]) + end, + ?t:fail(premature_death); + _ -> + %% Don't match arity; it is different in debug and + %% optimized emulator + [{status, suspended}, + {current_function, {erlang, bif_return_trap, _}}] = Pinfo, + receive + {'DOWN', M, process, P, Reason} -> + ?t:format("~p died with exit reason ~p~n", [P, Reason]), + normal = Reason + end + end. + +remote_is_process_alive(Pid) -> + rpc:call(node(Pid), erlang, is_process_alive, + [Pid]). + +joey_killer(Pid) -> + exit(Pid, joey_said_die), + until(fun () -> false == remote_is_process_alive(Pid) end). + +tail_joey_killer(Pid) -> + exit(Pid, joey_said_die). + +applied_joey_killer(Pid) -> + apply(erlang, exit, [Pid, joey_said_die]), + until(fun () -> false == remote_is_process_alive(Pid) end). + +tail_applied_joey_killer(Pid) -> + apply(erlang, exit, [Pid, joey_said_die]). + +sink(Name) -> + register(Name, self()), + sink1(). + +sink1() -> + receive + _Any -> sink1() + end. + +lost_exit(doc) -> + "Test that EXIT and DOWN messages send to another node are not lost if " + "if the distribution port is busy."; +lost_exit(Config) when is_list(Config) -> + ?line {ok, Node} = start_node(lost_exit), + + Tracer = case os:getenv("TRACE_BUSY_DIST_PORT") of + "true" -> start_busy_dist_port_tracer(); + _ -> false + end, + + Self = self(), + Die = make_ref(), + ?line R1 = spawn(fun () -> receive after infinity -> ok end end), + ?line MR1 = erlang:monitor(process, R1), + + ?line {L1, ML1} = spawn_monitor(fun() -> + link(R1), + Self ! {self(), linked}, + receive + Die -> + exit(controlled_suicide) + end + end), + + ?line R2 = spawn(fun () -> + M = erlang:monitor(process, L1), + receive + {'DOWN', M, process, L1, R} -> + Self ! {self(), got_down_message, L1, R} + end + end), + + ?line receive {L1, linked} -> ok end, + + Busy = make_busy(Node, 2000), + receive after 100 -> ok end, + L1 ! Die, + ?line receive + {'DOWN', ML1, process, L1, RL1} -> + ?line controlled_suicide = RL1 + end, + receive after 500 -> ok end, + unmake_busy(Busy), + + ?line receive + {'DOWN', MR1, process, R1, RR1} -> + ?line controlled_suicide = RR1 + end, + + ?line receive + {R2, got_down_message, L1, RR2} -> + ?line controlled_suicide = RR2 + end, + + %% Done. + ?line stop_busy_dist_port_tracer(Tracer), + ?line stop_node(Node), + ok. + +dummy_waiter() -> + receive + after infinity -> + ok + end. + +link_to_dead(doc) -> + ["Test that linking to a dead remote process gives an EXIT message ", + "AND that the link is teared down."]; +link_to_dead(Config) when is_list(Config) -> + ?line process_flag(trap_exit, true), + ?line {ok, Node} = start_node(link_to_dead), +% ?line monitor_node(Node, true), + ?line net_adm:ping(Node), %% Ts_cross_server workaround. + ?line Pid = spawn(Node, ?MODULE, dead_process, []), + receive + after 5000 -> ok + end, + ?line link(Pid), + ?line receive + {'EXIT', Pid, noproc} -> + ok; + Other -> + ?line test_server:fail({unexpected_message, Other}) + after 5000 -> + ?line test_server:fail(nothing_received) + end, + ?line {links, Links} = process_info(self(), links), + ?line io:format("Pid=~p, links=~p", [Pid, Links]), + ?line false = lists:member(Pid, Links), + ?line stop_node(Node), + ?line receive + Message -> + ?line test_server:fail({unexpected_message, Message}) + after 3000 -> + ok + end, + ok. + +dead_process() -> + erlang:error(die). + +link_to_dead_new_node(doc) -> + ["Test that linking to a pid on node that has gone and restarted gives ", + "the correct EXIT message (OTP-2304)."]; +link_to_dead_new_node(Config) when is_list(Config) -> + ?line process_flag(trap_exit, true), + + %% Start the node, get a Pid and stop the node again. + ?line {ok, Node} = start_node(link_to_dead_new_node), + ?line Pid = spawn(Node, ?MODULE, dead_process, []), + ?line stop_node(Node), + + %% Start a new node with the same name. + ?line {ok, Node} = start_node(link_to_dead_new_node), + ?line link(Pid), + ?line receive + {'EXIT', Pid, noproc} -> + ok; + Other -> + ?line test_server:fail({unexpected_message, Other}) + after 5000 -> + ?line test_server:fail(nothing_received) + end, + + %% Make sure that the link wasn't created. + ?line {links, Links} = process_info(self(), links), + ?line io:format("Pid=~p, links=~p", [Pid, Links]), + ?line false = lists:member(Pid, Links), + ?line stop_node(Node), + ?line receive + Message -> + ?line test_server:fail({unexpected_message, Message}) + after 3000 -> + ok + end, + ok. + +applied_monitor_node(doc) -> + "Test that monitor_node/2 works when applied."; +applied_monitor_node(Config) when is_list(Config) -> + ?line NonExisting = list_to_atom("__non_existing__@" ++ hostname()), + + %% Tail-recursive call to apply (since the node is non-existing, + %% there will be a trap). + + ?line true = tail_apply(erlang, monitor_node, [NonExisting, true]), + ?line [{nodedown, NonExisting}] = test_server:messages_get(), + + %% Ordinary call (with trap). + + ?line true = apply(erlang, monitor_node, [NonExisting, true]), + ?line [{nodedown, NonExisting}] = test_server:messages_get(), + + ok. + +tail_apply(M, F, A) -> + apply(M, F, A). + +ref_port_roundtrip(doc) -> + "Test that sending a port or reference to another node and back again " + "doesn't correct them in any way."; +ref_port_roundtrip(Config) when is_list(Config) -> + ?line process_flag(trap_exit, true), + ?line Port = open_port({spawn, efile}, []), + ?line Ref = make_ref(), + ?line {ok, Node} = start_node(ref_port_roundtrip), + ?line net_adm:ping(Node), + ?line Term = {Port, Ref}, + ?line io:format("Term before: ~p", [show_term(Term)]), + ?line Pid = spawn_link(Node, ?MODULE, roundtrip, [Term]), + ?line receive after 5000 -> ok end, + ?line stop_node(Node), + ?line receive + {'EXIT', Pid, {Port, Ref}} -> + ?line io:format("Term after: ~p", [show_term(Term)]), + ok; + Other -> + ?line io:format("Term after: ~p", [show_term(Term)]), + ?line test_server:fail({unexpected, Other}) + after 10000 -> + ?line test_server:fail(timeout) + end, + ok. + +roundtrip(Term) -> + exit(Term). + +nil_roundtrip(doc) -> + "Test that the smallest external term [] aka NIL can be sent to " + "another node node and back again."; +nil_roundtrip(Config) when is_list(Config) -> + ?line process_flag(trap_exit, true), + ?line {ok, Node} = start_node(nil_roundtrip), + ?line net_adm:ping(Node), + ?line Pid = spawn_link(Node, ?MODULE, bounce, [self()]), + ?line Pid ! [], + ?line receive + [] -> + ?line receive + {'EXIT', Pid, []} -> + ?line stop_node(Node), + ok + end + end. + +bounce(Dest) -> + receive Msg -> + Dest ! Msg, + exit(Msg) + end. + +show_term(Term) -> + binary_to_list(term_to_binary(Term)). + +stop_dist(doc) -> + ["Tests behaviour after net_kernel:stop (OTP-2586)."]; +stop_dist(Config) when is_list(Config) -> + ?line Str = os:cmd(atom_to_list(lib:progname()) + ++ " -noshell -pa " + ++ ?config(data_dir, Config) + ++ " -s run"), + %% The "true" may be followed by an error report, so ignore anything that + %% follows it. + ?line "true\n"++_ = Str, + + %% "May fail on FreeBSD due to differently configured name lookup - ask Arndt", + %% if you can find him. + + ok. + +trap_bif(doc) -> + ["Verifies that BIFs which are traps to Erlang work (OTP-2680)."]; +trap_bif(suite) -> [trap_bif_1, trap_bif_2, trap_bif_3]. + +trap_bif_1(doc) -> + [""]; +trap_bif_1(Config) when is_list(Config) -> + ?line {true} = tr1(), + ok. + +trap_bif_2(doc) -> + [""]; +trap_bif_2(Config) when is_list(Config) -> + ?line {true} = tr2(), + ok. + +trap_bif_3(doc) -> + [""]; +trap_bif_3(Config) when is_list(Config) -> + ?line {hoo} = tr3(), + ok. + +tr1() -> + ?line NonExisting = 'abc@boromir', + ?line X = erlang:monitor_node(NonExisting, true), + {X}. + +tr2() -> + ?line NonExisting = 'abc@boromir', + ?line X = apply(erlang, monitor_node, [NonExisting, true]), + {X}. + +tr3() -> + ?line NonExisting = 'abc@boromir', + ?line X = {NonExisting, glirp} ! hoo, + {X}. + + + +dist_auto_connect(doc) -> + ["Tests the kernel parameter 'dist_auto_connect'."]; +dist_auto_connect(suite) -> + [dist_auto_connect_never, dist_auto_connect_once]. + +% This has to be done by nodes with differrent cookies, otherwise global +% will connect nodes, which is correct, but makes it hard to test. +% * Start two nodes, n1 and n2. n2 with the dist_auto_connect once parameter +% * n2 pings n1 -> connection +% * check that they now know each other +% * Kill n1 +% * Make sure n2 gets pang when pinging n1 +% * restart n1 +% * Make sure n2 *still gets pang*! +% * Ping n2 from n1 -> pong +% * n2 now also gets pong when pinging n1 +% * disconnect n2 from n1 +% * n2 gets pang when pinging n1 +% * n2 forces connection by using net_kernel:connect_node (ovverrides) +% * n2 gets pong when pinging n1. +dist_auto_connect_once(doc) -> "Test the dist_auto_connect once kernel parameter"; +dist_auto_connect_once(Config) when is_list(Config) -> + ?line Sock = start_relay_node(dist_auto_connect_relay_node,[]), + ?line NN = inet_rpc_nodename(Sock), + ?line Sock2 = start_relay_node(dist_auto_connect_once_node, + "-kernel dist_auto_connect once"), + ?line NN2 = inet_rpc_nodename(Sock2), + ?line {ok,[]} = do_inet_rpc(Sock,erlang,nodes,[]), + ?line {ok, pong} = do_inet_rpc(Sock2,net_adm,ping,[NN]), + ?line {ok,[NN2]} = do_inet_rpc(Sock,erlang,nodes,[]), + ?line {ok,[NN]} = do_inet_rpc(Sock2,erlang,nodes,[]), + ?line [_,HostPartPeer] = string:tokens(atom_to_list(NN),"@"), + ?line [_,MyHostPart] = string:tokens(atom_to_list(node()),"@"), + % Give net_kernel a chance to change the state of the node to up to. + ?line receive after 1000 -> ok end, + case HostPartPeer of + MyHostPart -> + ?line ok = stop_relay_node(Sock), + ?line {ok,pang} = do_inet_rpc(Sock2,net_adm,ping,[NN]); + _ -> + ?line {ok, true} = do_inet_rpc(Sock,net_kernel,disconnect,[NN2]), + receive + after 500 -> ok + end + end, + ?line {ok, []} = do_inet_rpc(Sock2,erlang,nodes,[]), + Sock3 = case HostPartPeer of + MyHostPart -> + ?line start_relay_node(dist_auto_connect_relay_node,[]); + _ -> + Sock + end, + ?line TS1 = timestamp(), + ?line {ok, pang} = do_inet_rpc(Sock2,net_adm,ping,[NN]), + ?line TS2 = timestamp(), + RefT = net_kernel:connecttime() - 1000, + ?line true = ((TS2 - TS1) < RefT), + ?line TS3 = timestamp(), + ?line {ok, true} = do_inet_rpc(Sock2,erlang,monitor_node, + [NN,true,[allow_passive_connect]]), + ?line TS4 = timestamp(), + ?line true = ((TS4 - TS3) > RefT), + ?line {ok, pong} = do_inet_rpc(Sock3,net_adm,ping,[NN2]), + ?line {ok, pong} = do_inet_rpc(Sock2,net_adm,ping,[NN]), + ?line {ok, true} = do_inet_rpc(Sock3,net_kernel,disconnect,[NN2]), + receive + after 500 -> ok + end, + ?line {ok, pang} = do_inet_rpc(Sock2,net_adm,ping,[NN]), + ?line {ok, true} = do_inet_rpc(Sock2,net_kernel,connect_node,[NN]), + ?line {ok, pong} = do_inet_rpc(Sock2,net_adm,ping,[NN]), + ?line stop_relay_node(Sock3), + ?line stop_relay_node(Sock2). + + + +%% Start a relay node and a lonely (dist_auto_connect never) node. +%% Lonely node pings relay node. That should fail. +%% Lonely node connects to relay node with net_kernel:connect_node/1. +%% Result is sent here through relay node. +dist_auto_connect_never(Config) when is_list(Config) -> + Self = self(), + ?line {ok, RelayNode} = + start_node(dist_auto_connect_relay), + ?line spawn(RelayNode, + fun() -> + register(dist_auto_connect_relay, self()), + dist_auto_connect_relay(Self) + end), + ?line {ok, Handle} = dist_auto_connect_start(dist_auto_connect, never), + ?line Result = + receive + {do_dist_auto_connect, ok} -> + ok; + {do_dist_auto_connect, Error} -> + {error, Error}; + Other -> + {error, Other} + after 32000 -> + timeout + end, + ?line stop_node(RelayNode), + ?line Stopped = dist_auto_connect_stop(Handle), + ?line Junk = + receive + {do_dist_auto_connect, _} = J -> + J + after 0 -> + ok + end, + ?line {ok, ok, ok} = {Result, Stopped, Junk}, + ok. + + +do_dist_auto_connect([never]) -> + Node = list_to_atom("dist_auto_connect_relay@" ++ hostname()), + io:format("~p:do_dist_auto_connect([false]) Node=~p~n", + [?MODULE, Node]), + Ping = net_adm:ping(Node), + io:format("~p:do_dist_auto_connect([false]) Ping=~p~n", + [?MODULE, Ping]), + Result = case Ping of + pang -> ok; + _ -> {error, Ping} + end, + io:format("~p:do_dist_auto_connect([false]) Result=~p~n", + [?MODULE, Result]), + net_kernel:connect_node(Node), + catch {dist_auto_connect_relay, Node} ! {do_dist_auto_connect, Result}; +% receive after 1000 -> ok end, +% halt(); + +do_dist_auto_connect(Arg) -> + io:format("~p:do_dist_auto_connect(~p)~n", + [?MODULE, Arg]), + receive after 10000 -> ok end, + halt(). + + +dist_auto_connect_start(Name, Value) when is_atom(Name) -> + dist_auto_connect_start(atom_to_list(Name), Value); +dist_auto_connect_start(Name, Value) when is_list(Name), is_atom(Value) -> + Node = list_to_atom(lists:append([Name, "@", hostname()])), + ModuleDir = filename:dirname(code:which(?MODULE)), + ValueStr = atom_to_list(Value), + Cookie = atom_to_list(erlang:get_cookie()), + Cmd = lists:concat( + [%"xterm -e ", + atom_to_list(lib:progname()), +% " -noinput ", + " -detached ", + long_or_short(), " ", Name, + " -setcookie ", Cookie, + " -pa ", ModuleDir, + " -s ", atom_to_list(?MODULE), + " do_dist_auto_connect ", ValueStr, + " -kernel dist_auto_connect ", ValueStr]), + io:format("~p:dist_auto_connect_start() cmd: ~p~n", [?MODULE, Cmd]), + Port = open_port({spawn, Cmd}, [stream]), + {ok, {Port, Node}}. + + +dist_auto_connect_stop({Port, Node}) -> + Pid = spawn_link(fun() -> rpc:call(Node, erlang, halt, []) end), + dist_auto_connect_stop(Port, Node, Pid, 5000). + +dist_auto_connect_stop(Port, _Node, Pid, N) when is_integer(N), N =< 0 -> + exit(Pid, normal), + catch erlang:port_close(Port), + Result = {error, node_not_down}, + io:format("~p:dist_auto_connect_stop() ~p~n", [?MODULE, Result]), + Result; +dist_auto_connect_stop(Port, Node, Pid, N) when is_integer(N) -> + case net_adm:ping(Node) of + pong -> + receive after 100 -> ok end, + dist_auto_connect_stop(Port, Node, Pid, N-100); + pang -> + exit(Pid, normal), + catch erlang:port_close(Port), + io:format("~p:dist_auto_connect_stop() ok~n", [?MODULE]), + ok + end. + + +dist_auto_connect_relay(Parent) -> + receive X -> + catch Parent ! X + end, + dist_auto_connect_relay(Parent). + + +dist_parallel_send(doc) -> + []; +dist_parallel_send(suite) -> + []; +dist_parallel_send(Config) when is_list(Config) -> + ?line {ok, RNode} = start_node(dist_parallel_receiver), + ?line {ok, SNode} = start_node(dist_parallel_sender), + ?line WatchDog = spawn_link( + fun () -> + TRef = erlang:start_timer((?DEFAULT_TIMETRAP + div 2), + self(), + oops), + receive + {timeout, TRef, _ } -> + spawn(SNode, + fun () -> + abort(timeout) + end), + spawn(RNode, + fun () -> + abort(timeout) + end) +%% rpc:cast(SNode, erlang, halt, +%% ["Timetrap (sender)"]), +%% rpc:cast(RNode, erlang, halt, +%% ["Timetrap (receiver)"]) + end + end), + ?line MkSndrs = fun (Receiver) -> + lists:map(fun (_) -> + spawn_link(SNode, + ?MODULE, + dist_parallel_sender, + [self(), + Receiver, + 1000]) + end, + lists:seq(1, 64)) + end, + ?line SndrsStart = fun (Sndrs) -> + Parent = self(), + spawn_link( + SNode, + fun () -> + lists:foreach(fun (P) -> + P ! {go, Parent} + end, + Sndrs) + end) + end, + ?line SndrsWait = fun (Sndrs) -> + lists:foreach(fun (P) -> + receive {P, done} -> ok end + end, + Sndrs) + end, + ?line DPR = spawn_link(RNode, ?MODULE, dist_parallel_receiver, []), + ?line Sndrs1 = MkSndrs(DPR), + ?line SndrsStart(Sndrs1), + ?line SndrsWait(Sndrs1), + ?line unlink(DPR), + ?line exit(DPR, bang), + + ?line DEPR = spawn_link(RNode, ?MODULE, dist_evil_parallel_receiver, []), + ?line Sndrs2 = MkSndrs(DEPR), + ?line SndrsStart(Sndrs2), + ?line SndrsWait(Sndrs2), + ?line unlink(DEPR), + ?line exit(DEPR, bang), + + ?line unlink(WatchDog), + ?line exit(WatchDog, bang), + + ?line stop_node(RNode), + ?line stop_node(SNode), + + ?line ok. + +do_dist_parallel_sender(Parent, _Receiver, 0) -> + Parent ! {self(), done}; +do_dist_parallel_sender(Parent, Receiver, N) -> + Receiver ! {self(), "Some data"}, + do_dist_parallel_sender(Parent, Receiver, N-1). + +dist_parallel_sender(Parent, Receiver, N) -> + receive {go, Parent} -> ok end, + do_dist_parallel_sender(Parent, Receiver, N). + +dist_parallel_receiver() -> + receive {_Sender, _Data} -> ok end, + dist_parallel_receiver(). + +dist_evil_parallel_receiver() -> + receive {Sender, _Data} -> ok end, + net_kernel:disconnect(node(Sender)), + dist_evil_parallel_receiver(). + +atom_roundtrip(Config) when is_list(Config) -> + ?line AtomData = atom_data(), + ?line verify_atom_data(AtomData), + ?line {ok, Node} = start_node(Config), + ?line do_atom_roundtrip(Node, AtomData), + ?line stop_node(Node), + ?line ok. + +atom_roundtrip_r12b(Config) when is_list(Config) -> + case ?t:is_release_available("r12b") of + true -> + ?line AtomData = atom_data(), + ?line verify_atom_data(AtomData), + ?line {ok, Node} = start_node(Config, [], "r12b"), + ?line do_atom_roundtrip(Node, AtomData), + ?line stop_node(Node), + ?line ok; + false -> + ?line {skip,"No OTP R12B available"} + end. + +do_atom_roundtrip(Node, AtomData) -> + ?line Parent = self(), + ?line Proc = spawn_link(Node, fun () -> verify_atom_data_loop(Parent) end), + ?line Proc ! {self(), AtomData}, + ?line receive {Proc, AD1} -> AtomData = AD1 end, + ?line Proc ! {self(), AtomData}, + ?line receive {Proc, AD2} -> AtomData = AD2 end, + ?line RevAtomData = lists:reverse(AtomData), + ?line Proc ! {self(), RevAtomData}, + ?line receive {Proc, RAD1} -> RevAtomData = RAD1 end, + ?line unlink(Proc), + ?line exit(Proc, bang), + ?line ok. + +verify_atom_data_loop(From) -> + receive + {From, AtomData} -> + verify_atom_data(AtomData), + From ! {self(), AtomData}, + verify_atom_data_loop(From) + end. + +atom_data() -> + lists:map(fun (N) -> + ATxt = "a"++integer_to_list(N), + {list_to_atom(ATxt), ATxt} + end, + lists:seq(1, 2000)). + +verify_atom_data(AtomData) -> + lists:foreach(fun ({Atom, AtomTxt}) -> + AtomTxt = atom_to_list(Atom) + end, + AtomData). + +contended_atom_cache_entry(Config) when is_list(Config) -> + ?line TestServer = self(), + ?line ProcessPairs = 10, + ?line Msgs = 100000, + ?line {ok, SNode} = start_node(Config), + ?line {ok, RNode} = start_node(Config), + ?line Success = make_ref(), + ?line Mstr + = spawn_link( + SNode, + fun () -> + erts_debug:set_internal_state(available_internal_state, + true), + Master = self(), + CIX = get_cix(), + TestAtoms = get_conflicting_atoms(CIX, ProcessPairs), + io:format("Testing with the following atoms all using " + "cache index ~p:~n ~p~n", + [CIX, TestAtoms]), + Ps = lists:map( + fun (A) -> + Ref = make_ref(), + R = spawn_link( + RNode, + fun () -> + Atom = receive + {Ref, txt, ATxt} -> + list_to_atom( + ATxt) + end, + receive_ref_atom(Ref, + Atom, + Msgs), + Master ! {self(), success} + end), + S = spawn_link( + SNode, + fun () -> + receive go -> ok end, + R ! {Ref, + txt, + atom_to_list(A)}, + send_ref_atom(R, Ref, A, Msgs) + end), + {S, R} + end, + TestAtoms), + lists:foreach(fun ({S, _}) -> + S ! go + end, + Ps), + lists:foreach(fun ({_, R}) -> + receive {R, success} -> ok end + end, + Ps), + TestServer ! Success + end), + ?line receive + Success -> + ok + end, + ?line stop_node(SNode), + ?line stop_node(RNode), + ?line ok. + +send_ref_atom(To, Ref, Atom, 0) -> + ok; +send_ref_atom(To, Ref, Atom, N) -> + To ! {Ref, Atom}, + send_ref_atom(To, Ref, Atom, N-1). + +receive_ref_atom(Ref, Atom, 0) -> + ok; +receive_ref_atom(Ref, Atom, N) -> + receive + {Ref, Value} -> + Atom = Value + end, + receive_ref_atom(Ref, Atom, N-1). + +get_cix() -> + get_cix(1000). + +get_cix(CIX) when is_integer(CIX), CIX < 0 -> + get_cix(0); +get_cix(CIX) when is_integer(CIX) -> + get_cix(CIX, + unwanted_cixs(), + erts_debug:get_internal_state(max_atom_out_cache_index)). + +get_cix(CIX, Unwanted, MaxCIX) when CIX > MaxCIX -> + get_cix(0, Unwanted, MaxCIX); +get_cix(CIX, Unwanted, MaxCIX) -> + case lists:member(CIX, Unwanted) of + true -> get_cix(CIX+1, Unwanted, MaxCIX); + false -> CIX + end. + +unwanted_cixs() -> + lists:map(fun (Node) -> + erts_debug:get_internal_state({atom_out_cache_index, + Node}) + end, + nodes()). + + +get_conflicting_atoms(CIX, 0) -> + []; +get_conflicting_atoms(CIX, N) -> + {A, B, C} = now(), + Atom = list_to_atom("atom" ++ integer_to_list(A*1000000000000 + + B*1000000 + + C)), + case erts_debug:get_internal_state({atom_out_cache_index, Atom}) of + CIX -> + [Atom|get_conflicting_atoms(CIX, N-1)]; + _ -> + get_conflicting_atoms(CIX, N) + end. + + +bad_dist_ext(doc) -> []; +bad_dist_ext(suite) -> + [bad_dist_ext_receive, + bad_dist_ext_process_info, + bad_dist_ext_control, + bad_dist_ext_connection_id]. + + +bad_dist_ext_receive(Config) when is_list(Config) -> + ?line {ok, Offender} = start_node(bad_dist_ext_receive_offender), + ?line {ok, Victim} = start_node(bad_dist_ext_receive_victim), + ?line start_node_monitors([Offender,Victim]), + + ?line Parent = self(), + + ?line P = spawn_link(Victim, + fun () -> + Parent ! {self(), started}, + receive check_msgs -> ok end, + bad_dist_ext_check_msgs([one, + two, + three]), + Parent ! {self(), messages_checked}, + receive done -> ok end + end), + + ?line receive {P, started} -> ok end, + ?line pong = rpc:call(Victim, net_adm, ping, [Offender]), + ?line verify_up(Offender, Victim), + ?line true = lists:member(Offender, rpc:call(Victim, erlang, nodes, [])), + ?line P ! one, + ?line send_bad_msg(Offender, P), + ?line P ! two, + ?line verify_down(Offender, connection_closed, Victim, killed), + ?line {message_queue_len, 2} + = rpc:call(Victim, erlang, process_info, [P, message_queue_len]), + + ?line Suspended = make_ref(), + ?line S = spawn(Victim, + fun () -> + erlang:suspend_process(P), + Parent ! Suspended, + receive after infinity -> ok end + end), + ?line MS = erlang:monitor(process, S), + ?line receive Suspended -> ok end, + ?line pong = rpc:call(Victim, net_adm, ping, [Offender]), + ?line verify_up(Offender, Victim), + ?line true = lists:member(Offender, rpc:call(Victim, erlang, nodes, [])), + ?line send_bad_msgs(Offender, P, 5), + ?line true = lists:member(Offender, rpc:call(Victim, erlang, nodes, [])), + ?line P ! three, + ?line send_bad_msgs(Offender, P, 5), + + %% Make sure bad msgs has reached Victim + ?line rpc:call(Offender, rpc, call, [Victim, erlang, node, []]), + + ?line verify_still_up(Offender, Victim), + ?line {message_queue_len, 13} + = rpc:call(Victim, erlang, process_info, [P, message_queue_len]), + + ?line exit(S, bang), + ?line receive {'DOWN', MS, process, S, bang} -> ok end, + ?line verify_down(Offender, connection_closed, Victim, killed), + ?line {message_queue_len, 3} + = rpc:call(Victim, erlang, process_info, [P, message_queue_len]), + + ?line P ! check_msgs, + ?line receive {P, messages_checked} -> ok end, + + ?line {message_queue_len, 0} + = rpc:call(Victim, erlang, process_info, [P, message_queue_len]), + + ?line P ! done, + ?line unlink(P), + ?line verify_no_down(Offender, Victim), + ?line stop_node(Offender), + ?line stop_node(Victim). + + +bad_dist_ext_process_info(Config) when is_list(Config) -> + ?line {ok, Offender} = start_node(bad_dist_ext_process_info_offender), + ?line {ok, Victim} = start_node(bad_dist_ext_process_info_victim), + ?line start_node_monitors([Offender,Victim]), + + ?line Parent = self(), + ?line P = spawn_link(Victim, + fun () -> + Parent ! {self(), started}, + receive check_msgs -> ok end, + bad_dist_ext_check_msgs([one, two]), + Parent ! {self(), messages_checked}, + receive done -> ok end + end), + + ?line receive {P, started} -> ok end, + ?line P ! one, + + ?line Suspended = make_ref(), + ?line S = spawn(Victim, + fun () -> + erlang:suspend_process(P), + Parent ! Suspended, + receive after infinity -> ok end + end), + + ?line receive Suspended -> ok end, + ?line pong = rpc:call(Victim, net_adm, ping, [Offender]), + ?line verify_up(Offender, Victim), + ?line send_bad_msgs(Offender, P, 5), + + ?line P ! two, + ?line send_bad_msgs(Offender, P, 5), + + %% Make sure bad msgs has reached Victim + ?line rpc:call(Offender, rpc, call, [Victim, erlang, node, []]), + + ?line verify_still_up(Offender, Victim), + ?line {message_queue_len, 12} + = rpc:call(Victim, erlang, process_info, [P, message_queue_len]), + ?line verify_still_up(Offender, Victim), + ?line [{message_queue_len, 2}, + {messages, [one, two]}] + = rpc:call(Victim, erlang, process_info, [P, [message_queue_len, + messages]]), + ?line verify_down(Offender, connection_closed, Victim, killed), + + ?line P ! check_msgs, + ?line exit(S, bang), + ?line receive {P, messages_checked} -> ok end, + + ?line {message_queue_len, 0} + = rpc:call(Victim, erlang, process_info, [P, message_queue_len]), + + ?line P ! done, + ?line unlink(P), + ?line verify_no_down(Offender, Victim), + ?line stop_node(Offender), + ?line stop_node(Victim). + +bad_dist_ext_control(Config) when is_list(Config) -> + ?line {ok, Offender} = start_node(bad_dist_ext_control_offender), + ?line {ok, Victim} = start_node(bad_dist_ext_control_victim), + ?line start_node_monitors([Offender,Victim]), + + ?line pong = rpc:call(Victim, net_adm, ping, [Offender]), + ?line verify_up(Offender, Victim), + ?line send_bad_dhdr(Offender, Victim), + ?line verify_down(Offender, connection_closed, Victim, killed), + + ?line pong = rpc:call(Victim, net_adm, ping, [Offender]), + ?line verify_up(Offender, Victim), + ?line send_bad_ctl(Offender, Victim), + ?line verify_down(Offender, connection_closed, Victim, killed), + + ?line verify_no_down(Offender, Victim), + ?line stop_node(Offender), + ?line stop_node(Victim). + +bad_dist_ext_connection_id(Config) when is_list(Config) -> + ?line {ok, Offender} = start_node(bad_dist_ext_receive_offender), + ?line {ok, Victim} = start_node(bad_dist_ext_receive_victim), + ?line start_node_monitors([Offender,Victim]), + + ?line Parent = self(), + ?line P = spawn_link(Victim, + fun () -> + Parent ! {self(), started}, + receive check_msgs -> ok end, + bad_dist_ext_check_msgs([]), + Parent ! {self(), messages_checked}, + receive done -> ok end + end), + + ?line receive {P, started} -> ok end, + ?line Suspended = make_ref(), + ?line S = spawn(Victim, + fun () -> + erlang:suspend_process(P), + Parent ! Suspended, + receive after infinity -> ok end + end), + ?line MS = erlang:monitor(process, S), + ?line receive Suspended -> ok end, + ?line pong = rpc:call(Victim, net_adm, ping, [Offender]), + ?line verify_up(Offender, Victim), + ?line send_bad_msg(Offender, P), + + %% Make sure bad msg has reached Victim + ?line rpc:call(Offender, rpc, call, [Victim, erlang, node, []]), + + ?line {message_queue_len, 1} + = rpc:call(Victim, erlang, process_info, [P, message_queue_len]), + + ?line true = rpc:call(Offender, net_kernel, disconnect, [Victim]), + ?line verify_down(Offender, disconnect, Victim, connection_closed), + ?line pong = rpc:call(Offender, net_adm, ping, [Victim]), + + ?line verify_up(Offender, Victim), + %% We have a new connection between Offender and Victim, bad message + %% should not bring it down. + + ?line {message_queue_len, 1} + = rpc:call(Victim, erlang, process_info, [P, message_queue_len]), + + ?line exit(S, bang), + ?line receive {'DOWN', MS, process, S, bang} -> ok end, + %% Wait for a while (if the connection is taken down it might take a + %% while). + ?line receive after 2000 -> ok end, + ?line verify_still_up(Offender, Victim), + + ?line P ! check_msgs, + ?line receive {P, messages_checked} -> ok end, + + ?line {message_queue_len, 0} + = rpc:call(Victim, erlang, process_info, [P, message_queue_len]), + + ?line verify_still_up(Offender, Victim), + ?line P ! done, + ?line unlink(P), + ?line verify_no_down(Offender, Victim), + ?line stop_node(Offender), + ?line stop_node(Victim). + + +bad_dist_ext_check_msgs([]) -> + receive + Msg -> + exit({unexpected_message, Msg}) + after 0 -> + ok + end; +bad_dist_ext_check_msgs([M|Ms]) -> + receive + Msg -> + M = Msg, + bad_dist_ext_check_msgs(Ms) + end. + +-define(COOKIE, ''). +-define(DOP_LINK, 1). +-define(DOP_SEND, 2). +-define(DOP_EXIT, 3). +-define(DOP_UNLINK, 4). +-define(DOP_NODE_LINK, 5). +-define(DOP_REG_SEND, 6). +-define(DOP_GROUP_LEADER, 7). +-define(DOP_EXIT2, 8). + +-define(DOP_SEND_TT, 12). +-define(DOP_EXIT_TT, 13). +-define(DOP_REG_SEND_TT, 16). +-define(DOP_EXIT2_TT, 18). + +-define(DOP_MONITOR_P, 19). +-define(DOP_DEMONITOR_P, 20). +-define(DOP_MONITOR_P_EXIT, 21). + +dport_reg_send(Node, Name, Msg) -> + DPrt = case dport(Node) of + undefined -> + pong = net_adm:ping(Node), + dport(Node); + Prt -> + Prt + end, + port_command(DPrt, [dmsg_hdr(), + dmsg_ext({?DOP_REG_SEND, + self(), + ?COOKIE, + Name}), + dmsg_ext(Msg)]). + + +dport_send(To, Msg) -> + Node = node(To), + DPrt = case dport(Node) of + undefined -> + pong = net_adm:ping(Node), + dport(Node); + Prt -> + Prt + end, + port_command(DPrt, [dmsg_hdr(), + dmsg_ext({?DOP_SEND, + ?COOKIE, + To}), + dmsg_ext(Msg)]). + +%% send_bad_msgs(): +%% Send a valid distribution header and control message +%% but an invalid message. This invalid message will be +%% enqueued in the receivers message queue. +send_bad_msg(BadNode, To) -> + send_bad_msgs(BadNode, To, 1). + +send_bad_msgs(BadNode, To, Repeat) when is_atom(BadNode), + is_pid(To), + is_integer(Repeat) -> + Parent = self(), + Done = make_ref(), + spawn_link(BadNode, + fun () -> + Node = node(To), + pong = net_adm:ping(Node), + DPrt = dport(Node), + DData = [dmsg_hdr(), + dmsg_ext({?DOP_SEND, ?COOKIE, To}), + dmsg_bad_atom_cache_ref()], + repeat(fun () -> port_command(DPrt, DData) end, Repeat), + Parent ! Done + end), + receive Done -> ok end. + +%% send_bad_ctl(): +%% Send a valid distribution header but an invalid control message. +send_bad_ctl(BadNode, ToNode) when is_atom(BadNode), is_atom(ToNode) -> + Parent = self(), + Done = make_ref(), + spawn_link(BadNode, + fun () -> + pong = net_adm:ping(ToNode), + %% We creat a valid ctl msg and replace an + %% atom with an invalid atom cache reference + <<131,Replace/binary>> = term_to_binary(replace), + Ctl = dmsg_ext({?DOP_REG_SEND, + self(), + ?COOKIE, + replace}), + CtlBeginSize = size(Ctl) - size(Replace), + <<CtlBegin:CtlBeginSize/binary, Replace/binary>> = Ctl, + port_command(dport(ToNode), + [dmsg_fake_hdr2(), + CtlBegin, + dmsg_bad_atom_cache_ref(), + dmsg_ext({a, message})]), + Parent ! Done + end), + receive Done -> ok end. + +%% send_bad_dhr(): +%% Send an invalid distribution header +send_bad_dhdr(BadNode, ToNode) when is_atom(BadNode), is_atom(ToNode) -> + Parent = self(), + Done = make_ref(), + spawn_link(BadNode, + fun () -> + pong = net_adm:ping(ToNode), + port_command(dport(ToNode), dmsg_bad_hdr()), + Parent ! Done + end), + receive Done -> ok end. + +dport(Node) when is_atom(Node) -> + case catch erts_debug:get_internal_state(available_internal_state) of + true -> true; + _ -> erts_debug:set_internal_state(available_internal_state, true) + end, + erts_debug:get_internal_state({dist_port, Node}). + +dmsg_hdr() -> + [131, % Version Magic + $D, % Dist header + 0]. % No atom cache referenses + +dmsg_bad_hdr() -> + [131, % Version Magic + $D, % Dist header + 255]. % 255 atom references + + +dmsg_fake_hdr1() -> + A = <<"fake header atom 1">>, + [131, % Version Magic + $D, 1, 16#8, 0, size(A), A]. % Fake header + +dmsg_fake_hdr2() -> + A1 = <<"fake header atom 1">>, + A2 = <<"atom 2">>, + A3 = <<"atom 3">>, + [131, % Version Magic + $D, + 3, + 16#88, 16#08, % Flags + 0, size(A1), A1, + 1, size(A2), A2, + 2, size(A3), A3]. + +dmsg_ext(Term) -> + <<131, Res/binary>> = term_to_binary(Term), + Res. + +dmsg_bad_atom_cache_ref() -> + [$R, 137]. + +%%% Utilities + +timestamp() -> + {A,B,C} = erlang:now(), + (C div 1000) + (B * 1000) + (A * 1000000000). + +start_node(X) -> + start_node(X, [], []). + +start_node(X, Y) -> + start_node(X, Y, []). + +start_node(Name, Args, Rel) when is_atom(Name), is_list(Rel) -> + Pa = filename:dirname(code:which(?MODULE)), + Cookie = atom_to_list(erlang:get_cookie()), + RelArg = case Rel of + [] -> []; + _ -> [{erl,[{release,Rel}]}] + end, + test_server:start_node(Name, slave, + [{args, + Args++" -setcookie "++Cookie++" -pa "++Pa} + | RelArg]); +start_node(Config, Args, Rel) when is_list(Config), is_list(Rel) -> + Name = list_to_atom((atom_to_list(?MODULE) + ++ "-" + ++ atom_to_list(?config(testcase, Config)) + ++ "-" + ++ integer_to_list(timestamp()))), + start_node(Name, Args, Rel). + +stop_node(Node) -> + test_server:stop_node(Node). + +freeze_node(Node, MS) -> + Own = 300, + DoingIt = make_ref(), + Freezer = self(), + spawn_link(Node, + fun () -> + erts_debug:set_internal_state(available_internal_state, + true), + dport_send(Freezer, DoingIt), + receive after Own -> ok end, + erts_debug:set_internal_state(block, MS+Own) + end), + receive DoingIt -> ok end, + receive after Own -> ok end. + +inet_rpc_nodename({N,H,_Sock}) -> + list_to_atom(N++"@"++H). + +do_inet_rpc({_,_,Sock},M,F,A) -> + Bin = term_to_binary({M,F,A}), + gen_tcp:send(Sock,Bin), + case gen_tcp:recv(Sock,0) of + {ok, Bin2} -> + T = binary_to_term(Bin2), + {ok,T}; + Else -> + {error, Else} + end. + +inet_rpc_server([Host, PortList]) -> + Port = list_to_integer(PortList), + {ok, Sock} = gen_tcp:connect(Host, Port,[binary, {packet, 4}, + {active, false}]), + inet_rpc_server_loop(Sock). + +inet_rpc_server_loop(Sock) -> + case gen_tcp:recv(Sock,0) of + {ok, Bin} -> + {M,F,A} = binary_to_term(Bin), + Res = (catch apply(M,F,A)), + RB = term_to_binary(Res), + gen_tcp:send(Sock,RB), + inet_rpc_server_loop(Sock); + _ -> + erlang:halt() + end. + + +start_relay_node(Node, Args) -> + Pa = filename:dirname(code:which(?MODULE)), + Cookie = "NOT"++atom_to_list(erlang:get_cookie()), + {ok, LSock} = gen_tcp:listen(0, [binary, {packet, 4}, + {active, false}]), + {ok, Port} = inet:port(LSock), + {ok, Host} = inet:gethostname(), + RunArg = "-run " ++ atom_to_list(?MODULE) ++ " inet_rpc_server " ++ + Host ++ " " ++ integer_to_list(Port), + {ok, NN} = + test_server:start_node(Node, peer, + [{args, Args ++ + " -setcookie "++Cookie++" -pa "++Pa++" "++ + RunArg}]), + [N,H] = string:tokens(atom_to_list(NN),"@"), + {ok, Sock} = gen_tcp:accept(LSock), + pang = net_adm:ping(NN), + {N,H,Sock}. + +stop_relay_node({N,H,Sock}) -> + catch do_inet_rpc(Sock,erlang,halt,[]), + catch gen_tcp:close(Sock), + wait_dead(N,H,10). + +wait_dead(N,H,0) -> + {error,{not_dead,N,H}}; +wait_dead(N,H,X) -> + case erl_epmd:port_please(N,H) of + {port,_,_} -> + receive + after 1000 -> + ok + end, + wait_dead(N,H,X-1); + noport -> + ok; + Else -> + {error, {unexpected, Else}} + end. + + +start_node_monitors(Nodes) -> + Master = self(), + lists:foreach(fun (Node) -> + spawn(Node, + fun () -> + node_monitor(Master) + end) + end, + Nodes), + ok. + +node_monitor(Master) -> + Opts = [nodedown_reason,{node_type,all}], + Nodes0 = nodes(connected), + net_kernel:monitor_nodes(true, Opts), + Nodes1 = nodes(connected), + case lists:sort(Nodes0) == lists:sort(Nodes1) of + true -> + lists:foreach(fun (Node) -> + Master ! {nodeup, node(), Node} + end, + Nodes0), + ?t:format("~p ~p: ~p~n", [node(), erlang:now(), Nodes0]), + node_monitor_loop(Master); + false -> + net_kernel:monitor_nodes(false, Opts), + flush_node_changes(), + node_monitor(Master) + end. + +flush_node_changes() -> + receive + {NodeChange, _Node, _InfoList} when NodeChange == nodeup; + NodeChange == nodedown -> + flush_node_changes() + after 0 -> + ok + end. + +node_monitor_loop(Master) -> + receive + {nodeup, Node, InfoList} = Msg -> + Master ! {nodeup, node(), Node}, + ?t:format("~p ~p: ~p~n", [node(), erlang:now(), Msg]), + node_monitor_loop(Master); + {nodedown, Node, InfoList} = Msg -> + Reason = case lists:keysearch(nodedown_reason, 1, InfoList) of + {value, {nodedown_reason, R}} -> R; + _ -> undefined + end, + Master ! {nodedown, node(), Node, Reason}, + ?t:format("~p ~p: ~p~n", [node(), erlang:now(), Msg]), + node_monitor_loop(Master) + end. + +verify_up(A, B) -> + receive {nodeup, A, B} -> ok end, + receive {nodeup, B, A} -> ok end. + +verify_still_up(A, B) -> + true = lists:member(B, rpc:call(A, erlang, nodes, [connected])), + true = lists:member(A, rpc:call(B, erlang, nodes, [connected])), + verify_no_down(A, B). + +verify_no_down(A, B) -> + receive + {nodedown, A, B, _} = Msg0 -> + ?t:fail(Msg0) + after 0 -> + ok + end, + receive + {nodedown, B, A, _} = Msg1 -> + ?t:fail(Msg1) + after 0 -> + ok + end. + +verify_down(A, B) -> + receive {nodedown, A, B, _} -> ok end, + receive {nodedown, B, A, _} -> ok end. + +verify_down(A, ReasonA, B, ReasonB) -> + receive + {nodedown, A, B, _} = Msg0 -> + {nodedown, A, B, ReasonA} = Msg0 + end, + receive + {nodedown, B, A, _} = Msg1 -> + {nodedown, B, A, ReasonB} = Msg1 + end, + ok. + +hostname() -> + from($@, atom_to_list(node())). + +from(H, [H | T]) -> T; +from(H, [_ | T]) -> from(H, T); +from(_, []) -> []. + +fun_spawn(Fun) -> + fun_spawn(Fun, []). + +fun_spawn(Fun, Args) -> + spawn_link(erlang, apply, [Fun, Args]). + + +long_or_short() -> + case net_kernel:longnames() of + true -> " -name "; + false -> " -sname " + end. + +until(Fun) -> + case Fun() of + true -> + ok; + false -> + receive after 10 -> ok end, + until(Fun) + end. + +forever(Fun) -> + Fun(), + forever(Fun). + +abort(Why) -> + erts_debug:set_internal_state(available_internal_state, true), + erts_debug:set_internal_state(abort, Why). + + +start_busy_dist_port_tracer() -> + Tracer = spawn_link(fun () -> busy_dist_port_tracer() end), + erlang:system_monitor(Tracer, [busy_dist_port]), + Tracer. + +stop_busy_dist_port_tracer(Tracer) when is_pid(Tracer) -> + unlink(Tracer), + exit(Tracer, bye); +stop_busy_dist_port_tracer(_) -> + true. + +busy_dist_port_tracer() -> + receive + {monitor, _SuspendedProcess, busy_dist_port, _Port} = M -> + erlang:display(M), + busy_dist_port_tracer() + end. + +repeat(_Fun, 0) -> + ok; +repeat(Fun, N) -> + Fun(), + repeat(Fun, N-1). diff --git a/erts/emulator/test/distribution_SUITE_data/Makefile.src b/erts/emulator/test/distribution_SUITE_data/Makefile.src new file mode 100644 index 0000000000..0eebe48e74 --- /dev/null +++ b/erts/emulator/test/distribution_SUITE_data/Makefile.src @@ -0,0 +1,4 @@ +all: run + +run: + @erl_name@ -compile run diff --git a/erts/emulator/test/distribution_SUITE_data/run.erl b/erts/emulator/test/distribution_SUITE_data/run.erl new file mode 100644 index 0000000000..e2137a1ec5 --- /dev/null +++ b/erts/emulator/test/distribution_SUITE_data/run.erl @@ -0,0 +1,48 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(run). + +-compile(export_all). + +host() -> + from($@, atom_to_list(node())). + +from(H, [H | T]) -> T; +from(H, [_ | T]) -> from(H, T); +from(H, []) -> []. + +start() -> + net_kernel:start([fideridum,shortnames]), + {ok, Node} = slave:start(host(), heppel), + P = spawn(Node, a, b, []), + B1 = term_to_binary(P), + N1 = node(P), + ok = net_kernel:stop(), + N2 = node(P), + io:format("~w~n", [N1 == N2]), + if + N1 == N2 -> + init:stop(); + true -> + %% Make sure that the io:format/2 output is really written + %% (especially on Windows). + erlang:yield(), + init:stop() + end. diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl new file mode 100644 index 0000000000..39b2ed395f --- /dev/null +++ b/erts/emulator/test/driver_SUITE.erl @@ -0,0 +1,1993 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +%%% Purpose : Test interaction Erlang/Drivers (new features as of R3A) + +%%% Checks that new features (as of R3) of the Erlang/Driver +%%% implementation works as expected. +%%% +%%% Things that should be tested: +%%% - outputv +%%% - timeouts +%%% - queueing + +-module(driver_SUITE). +-export([all/1, + init_per_testcase/2, + fin_per_testcase/2, + end_per_suite/1, + outputv_echo/1, + timer/1, + timer_measure/1, + timer_cancel/1, + timer_change/1, + timer_delay/1, + queue_echo/1, + fun_to_port/1, + driver_unloaded/1, + io_ready_exit/1, + use_fallback_pollset/1, + bad_fd_in_pollset/1, + driver_event/1, + fd_change/1, + steal_control/1, + otp_6602/1, + 'driver_system_info_ver1.0'/1, + 'driver_system_info_ver1.1'/1, + driver_system_info_current_ver/1, + driver_monitor/1, + ioq_exit/1, + ioq_exit_ready_input/1, + ioq_exit_ready_output/1, + ioq_exit_timeout/1, + ioq_exit_ready_async/1, + ioq_exit_event/1, + ioq_exit_ready_input_async/1, + ioq_exit_ready_output_async/1, + ioq_exit_timeout_async/1, + ioq_exit_event_async/1, + zero_extended_marker_garb_drv/1, + invalid_extended_marker_drv/1, + larger_major_vsn_drv/1, + larger_minor_vsn_drv/1, + smaller_major_vsn_drv/1, + smaller_minor_vsn_drv/1, + peek_non_existing_queue/1, + otp_6879/1, + caller/1, + many_events/1, + missing_callbacks/1, + smp_select/1, + driver_select_use/1, + thread_mseg_alloc_cache_clean/1]). + +-export([bin_prefix/2]). + +-include("test_server.hrl"). + + +% First byte in communication with the timer driver +-define(START_TIMER, 0). +-define(CANCEL_TIMER, 1). +-define(DELAY_START_TIMER, 2). +-define(TIMER, 3). +-define(CANCELLED, 4). + +% First byte in communication with queue driver +-define(PUSHQ, 0). +-define(ENQ, 1). +-define(PUSHQ_BIN, 2). +-define(ENQ_BIN, 3). +-define(PUSHQV, 4). +-define(ENQV, 5). + +-define(DEQ, 6). +-define(BYTES_QUEUED, 7). +-define(READ_HEAD, 8). + +-define(RANDOM, random). + +% Max data size that is queued in one instance +-define(MAX_DATA_SIZE, 16384). + +% This is the allowed delay when testing the driver timer functionality +-define(delay, 100). + +-define(heap_binary_size, 64). + +init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> + Dog=?t:timetrap(?t:minutes(2)), + case catch erts_debug:get_internal_state(available_internal_state) of + true -> ok; + _ -> erts_debug:set_internal_state(available_internal_state, true) + end, + erlang:display({init_per_testcase, Case}), + ?line 0 = erts_debug:get_internal_state(check_io_debug), + [{watchdog, Dog},{testcase, Case}|Config]. + +fin_per_testcase(Case, Config) -> + Dog = ?config(watchdog, Config), + erlang:display({fin_per_testcase, Case}), + ?line 0 = erts_debug:get_internal_state(check_io_debug), + ?t:timetrap_cancel(Dog). + +end_per_suite(_Config) -> + catch erts_debug:set_internal_state(available_internal_state, false). + +all(suite) -> + [ + fun_to_port, + outputv_echo, + queue_echo, + timer, + driver_unloaded, + io_ready_exit, + use_fallback_pollset, + bad_fd_in_pollset, + driver_event, + fd_change, + steal_control, + otp_6602, + 'driver_system_info_ver1.0', + 'driver_system_info_ver1.1', + driver_system_info_current_ver, + driver_monitor, + ioq_exit, + zero_extended_marker_garb_drv, + invalid_extended_marker_drv, + larger_major_vsn_drv, + larger_minor_vsn_drv, + smaller_major_vsn_drv, + smaller_minor_vsn_drv, + peek_non_existing_queue, + otp_6879, + caller, + many_events, + missing_callbacks, + smp_select, + driver_select_use, + thread_mseg_alloc_cache_clean + ]. + +fun_to_port(doc) -> "Test sending a fun to port with an outputv-capable driver."; +fun_to_port(Config) when is_list(Config) -> + ?line Path = ?config(data_dir, Config), + ?line erl_ddll:start(), + ?line ok = load_driver(Path, outputv_drv), + + ?line fun_to_port_1(fun() -> 33 end), + ?line fun_to_port_1([fun() -> 42 end]), + ?line fun_to_port_1([1|fun() -> 42 end]), + L = build_io_list(65536), + ?line fun_to_port_1([L,fun() -> 42 end]), + ?line fun_to_port_1([L|fun() -> 42 end]), + ok. + +fun_to_port_1(Term) -> + Port = open_port({spawn,outputv_drv}, []), + {'EXIT',{badarg,_}} = (catch port_command(Port, Term)), + port_close(Port). + +build_io_list(0) -> []; +build_io_list(1) -> [7]; +build_io_list(N) -> + L = build_io_list(N div 2), + case N rem 2 of + 0 -> [L|L]; + 1 -> [7,L|L] + end. + + + +outputv_echo(doc) -> ["Test echoing data with a driver that supports outputv."]; +outputv_echo(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(10)), + Name = 'outputv_drv', + P = start_driver(Config, Name, true), + + ?line ov_test(P, {bin,0}), + ?line ov_test(P, {bin,1}), + ?line ov_test(P, {bin,2}), + ?line ov_test(P, {bin,3}), + ?line ov_test(P, {bin,4}), + ?line ov_test(P, {bin,5}), + ?line ov_test(P, {bin,6}), + ?line ov_test(P, {bin,7}), + ?line ov_test(P, {bin,8}), + ?line ov_test(P, {bin,15}), + ?line ov_test(P, {bin,16}), + ?line ov_test(P, {bin,17}), + + ?line ov_test(P, {list,0}), + ?line ov_test(P, {list,1}), + ?line ov_test(P, {list,2}), + ?line ov_test(P, [int,int,{list,0},int]), + ?line ov_test(P, [int,int,{list,1},int]), + ?line ov_test(P, [int,int,{list,2}]), + ?line ov_test(P, [{list,3},int,int,{list,2}]), + ?line ov_test(P, {list,33}), + + ?line ov_test(P, [{bin,0}]), + ?line ov_test(P, [{bin,1}]), + ?line ov_test(P, [{bin,2}]), + ?line ov_test(P, [{bin,3}]), + ?line ov_test(P, [{bin,4}]), + ?line ov_test(P, [{bin,5}]), + ?line ov_test(P, [{bin,6},int]), + ?line ov_test(P, [int,{bin,3}]), + ?line ov_test(P, [int|{bin,4}]), + ?line ov_test(P, [{bin,17},int,{bin,13}|{bin,3}]), + + ?line ov_test(P, [int,{bin,17},int,{bin,?heap_binary_size+1}|{bin,3}]), + + stop_driver(P, Name), + ?line test_server:timetrap_cancel(Dog), + ok. + +ov_test(Port, Template) -> + Self = self(), + spawn_opt(erlang, apply, [fun () -> ov_test(Self, Port, Template) end,[]], + [link,{fullsweep_after,0}]), + receive + done -> ok + end. + +ov_test(Parent, Port, Template) -> + true = port_connect(Port, self()), + + HeapData = build_data(Template), + io:format("Mostly heap binaries"), + ov_send_and_test(Port, HeapData, HeapData), + + %% Try sub binaries. + io:format("Mostly sub binaries of heap binaries"), + SubHeapData = make_sub_binaries(HeapData), + ov_send_and_test(Port, SubHeapData, HeapData), + + %% Try refc binaries. + io:format("Refc binaries"), + RefcData = make_refc_binaries(HeapData), + ov_send_and_test(Port, RefcData, RefcData), + + %% Try sub binaries of heap binaries. + io:format("Sub binaries of refc binaries"), + SubRefcData = make_sub_binaries(RefcData), + ov_send_and_test(Port, SubRefcData, RefcData), + io:format("", []), + + %% Garbage collect and make sure that there are no binaries left. + %% R7 note: + %% - dead variables on the stack are killed after last use, + %% - erlang:garbage_collect/0 collects garbage immediately. + %% (there used to be dummy functions here) + erlang:garbage_collect(), + {binary,[]} = process_info(self(), binary), + + %% Reassign Port back to parent and tell him we are done. + true = port_connect(Port, Parent), + Parent ! done. + +ov_send_and_test(Port, Data, ExpectedResult) -> + io:format("~p ! ~P", [Port,Data,12]), + Port ! {self(),{command,Data}}, + receive + {Port,{data,ReturnData}} -> + io:format("~p returned ~P", [Port,ReturnData,12]), + compare(ReturnData, ExpectedResult); + {Port,{data,OtherData}} -> + io:format("~p returned WRONG data ~p", [Port,OtherData]), + ?line test_server:fail(); + Wrong -> + ?line test_server:fail({unexpected_port_or_data,Wrong}) + end. + +compare(Got, Expected) -> + case {list_to_binary([Got]),list_to_binary([Expected])} of + {B,B} -> ok; + {_Gb,_Eb} -> + ?t:fail(got_bad_data) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Driver timer test suites +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +timer(suite) -> [timer_measure,timer_cancel,timer_delay,timer_change]. + +timer_measure(doc) -> ["Check that timers time out in good time."]; +timer_measure(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(1)), + Name = 'timer_drv', + ?line Port = start_driver(Config, Name, false), + + ?line try_timeouts(Port, 8997), + + ?line stop_driver(Port, Name), + ?line test_server:timetrap_cancel(Dog), + ok. + +try_timeouts(_, 0) -> ok; +try_timeouts(Port, Timeout) -> + ?line TimeBefore = now(), + ?line erlang:port_command(Port, <<?START_TIMER,Timeout:32>>), + receive + {Port,{data,[?TIMER]}} -> + ?line Elapsed = erl_millisecs() - erl_millisecs(TimeBefore), + io:format("Elapsed: ~p Timeout: ~p\n", [Elapsed,Timeout]), + if + Elapsed < Timeout -> + ?line ?t:fail(too_short); + Elapsed > Timeout + ?delay -> + ?line ?t:fail(too_long); + true -> + try_timeouts(Port, Timeout div 2) + end + after Timeout + ?delay -> + ?line test_server:fail("driver failed to timeout") + end. + +timer_cancel(doc) -> ["Try cancelling timers set in a driver."]; +timer_cancel(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(1)), + Name = 'timer_drv', + ?line Port = start_driver(Config, Name, false), + + ?line try_cancel(Port, 10000), + + ?line stop_driver(Port, Name), + ?line test_server:timetrap_cancel(Dog), + ok. + +try_cancel(Port, Timeout) -> + ?line T_before = erl_millisecs(), + Port ! {self(),{command,<<?START_TIMER,(Timeout + ?delay):32>>}}, + receive + {Port, {data, [?TIMER]}} -> + ?line test_server:fail("driver timed out before cancelling it") + after Timeout -> + Port ! {self(), {command, [?CANCEL_TIMER]}}, + receive + {Port, {data, [?TIMER]}} -> + ?line test_server:fail("driver timed out after cancelling it"); + {Port, {data, [?CANCELLED]}} -> + ?line Time_milli_secs = erl_millisecs() - T_before, + + io:format("Time_milli_secs: ~p Timeout: ~p\n", + [Time_milli_secs, Timeout]), + if + Time_milli_secs > (Timeout + ?delay) -> + ?line test_server:fail("too long real time"); + Timeout == 0 -> ok; + true -> try_cancel(Port, Timeout div 2) + end + after ?delay -> + test_server:fail("No message from driver") + end + end. + +%% Test that timers don't time out too early if we do a sleep +%% before setting a timer. + +timer_delay(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(1)), + Name = 'timer_drv', + ?line Port = start_driver(Config, Name, false), + + ?line TimeBefore = now(), + Timeout0 = 350, + ?line erlang:port_command(Port, <<?DELAY_START_TIMER,Timeout0:32>>), + Timeout = Timeout0 + + case os:type() of + {win32,_} -> 0; %Driver doesn't sleep on Windows. + _ -> 1000 + end, + receive + {Port,{data,[?TIMER]}} -> + ?line Elapsed = erl_millisecs() - erl_millisecs(TimeBefore), + io:format("Elapsed time: ~p Timeout: ~p\n", + [Elapsed,Timeout]), + if + Elapsed < Timeout -> + ?line ?t:fail(too_short); + Elapsed > Timeout + ?delay -> + ?line ?t:fail(too_long); + true -> + ok + end + end, + + ?line stop_driver(Port, Name), + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Test that driver_set_timer with new timout really changes +%% the timer (ticket OTP-5942), it didn't work before + +timer_change(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(1)), + Name = 'timer_drv', + ?line Port = start_driver(Config, Name, false), + + ?line try_change_timer(Port, 10000), + + ?line stop_driver(Port, Name), + ?line test_server:timetrap_cancel(Dog), + ok. + +try_change_timer(_Port, 0) -> ok; +try_change_timer(Port, Timeout) -> + ?line Timeout_3 = Timeout*3, + ?line TimeBefore = now(), + ?line erlang:port_command(Port, <<?START_TIMER,Timeout_3:32>>), + ?line erlang:port_command(Port, <<?START_TIMER,Timeout:32>>), + receive + {Port,{data,[?TIMER]}} -> + ?line Elapsed = erl_millisecs() - erl_millisecs(TimeBefore), + io:format("Elapsed: ~p Timeout: ~p\n", [Elapsed,Timeout]), + if + Elapsed < Timeout -> + ?line ?t:fail(too_short); + Elapsed > Timeout + ?delay -> + ?line ?t:fail(too_long); + true -> + try_timeouts(Port, Timeout div 2) + end + after Timeout + ?delay -> + ?line test_server:fail("driver failed to timeout") + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Queue test suites +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +queue_echo(doc) -> + ["1) Queue up data in a driver that uses the full driver_queue API to do this." + "2) Get the data back, a random amount at a time."]; +queue_echo(Config) when is_list(Config) -> + case ?t:is_native(?MODULE) of + true -> exit(crashes_native_code); + false -> queue_echo_1(Config) + end. + +queue_echo_1(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(10)), + Name = 'queue_drv', + ?line P = start_driver(Config, Name, true), + + ?line q_echo(P, [{?ENQ, {list,1}}, + {?ENQ, {list,0}}, + {?ENQ, {bin,0}}, + {?ENQ, {bin,1}}, + {?ENQ, {bin,2}}, + {?ENQ, {bin,3}}, + {?ENQ, {bin,4}}, + {?ENQ, {bin,5}}, + {?ENQ, {bin,600}}, + {?PUSHQ, {list,0}}, + {?PUSHQ, {list,1}}, + {?PUSHQ, {bin,0}}, + {?PUSHQ, {bin,1}}, + {?PUSHQ, {bin,888}}, + {?ENQ_BIN, {bin,0}}, + {?ENQ_BIN, {bin,1}}, + {?ENQ_BIN, {bin,2}}, + {?ENQ_BIN, {bin,3}}, + {?ENQ_BIN, {bin,4}}, + {?ENQ_BIN, {bin,777}}, + {?PUSHQ_BIN, {bin,0}}, + {?PUSHQ_BIN, {bin,1}}, + {?PUSHQ_BIN, {bin,334}}, + {?ENQV, [{bin,0},{list,1},{bin,1},{bin,555}]}, + {?ENQV, [{bin,0},{list,1},{bin,1}]}, + {?PUSHQV, [{bin,0},{list,1},{bin,1},{bin,319}]}]), + + ?line stop_driver(P, Name), + ?line test_server:timetrap_cancel(Dog), + ok. + +q_echo(Port, SpecList) -> + io:format("Heap binaries"), + HeapData = [{M,build_data(T)} || {M,T} <- SpecList], + {HeapDataReturn,HeapDataLen} = feed_driver(Port, HeapData), + dequeue(Port, HeapDataReturn, HeapDataLen, 1), + + %% Try sub binaries. + io:format("Sub binaries of heap binaries"), + SubHeapData = make_sub_binaries(HeapData), + %% The following line will generate a warning. + {HeapDataReturn,HeapDataLen} = feed_driver(Port, SubHeapData), + dequeue(Port, HeapDataReturn, HeapDataLen, 1), + + %% Try refc binaries. + io:format("Refc binaries"), + RefcData = make_refc_binaries(HeapData), + {RefcDataReturn,RefcDataLen} = feed_driver(Port, RefcData), + dequeue(Port, RefcDataReturn, RefcDataLen, 1), + + %% Try sub binaries of refc binaries. + io:format("Sub binaries of refc binaries"), + SubRefcData = make_sub_binaries(RefcData), + {RefcDataReturn,RefcDataLen} = feed_driver(Port, SubRefcData), + dequeue(Port, RefcDataReturn, RefcDataLen, 1), + + %% Try a writable binary. + io:format("Writable binaries"), + WritableBinData = make_writable_binaries(HeapData), + {WritableDataReturn,WritableDatalen} = feed_driver(Port, WritableBinData), + _ = append_to_writable_binaries(WritableBinData), + dequeue(Port, WritableDataReturn, WritableDatalen, 1), + + %% Try dequeing more than one byte at the time. + io:format("Heap binaries -- dequeueing more than one byte at the time"), + feed_and_dequeue(Port, HeapData, 2), + feed_and_dequeue(Port, HeapData, 3), + feed_and_dequeue(Port, HeapData, 4), + + io:format("\n"). + +feed_and_dequeue(Port, Data, DeqSize) -> + {DataReturn,DataLen} = feed_driver(Port, Data), + dequeue(Port, DataReturn, DataLen, DeqSize), + ok. + +%% Send all data according to the specification to the driver side (where it +%% is queued up for later return to this process). + +feed_driver(Port, Description) -> + feed_driver(Port, Description, <<>>, 0). + +feed_driver(Port, [], ExpectedInPort, Qb) -> + io:format("Expected in port: ~P", [ExpectedInPort,12]), + io:format("In port: ~P", [read_head(Port, Qb),12]), + {ExpectedInPort,Qb}; +feed_driver(Port, [{Method0,Data}|T], Expected_return, Qb_before) -> + Method = case Method0 of + ?RANDOM -> uniform(6)-1; + Other -> Other + end, + Size = size(list_to_binary([Data])), + + %% *********************************************************************** + %% NOTE! Never never never change this to io:format/2, as that will imply + %% message sending, and sending as message will spoil the test of + %% writable binaries. + + %% erlang:display({sending,method_name(Method),Data}), + %% *********************************************************************** + + queue_op(Port, Method, Data), + + Qb_in_driver = bytes_queued(Port), + case Qb_before + Size of + Qb_in_driver -> ok; + Sum -> + io:format("Qb_before: ~p\n" + "Qb_before+Size: ~p\n" + "Qb_in_driver: ~p", + [Qb_before,Sum,Qb_in_driver]), + ?t:fail() + end, + X_return = case Method of + ?ENQ -> list_to_binary([Expected_return,Data]); + ?PUSHQ -> list_to_binary([Data,Expected_return]); + ?PUSHQ_BIN -> list_to_binary([Data,Expected_return]); + ?ENQ_BIN -> list_to_binary([Expected_return,Data]); + ?PUSHQV -> list_to_binary([Data,Expected_return]); + ?ENQV -> list_to_binary([Expected_return,Data]) + end, + feed_driver(Port, T, X_return, Qb_before + Size). + +%% method_name(0) -> pushq; +%% method_name(1) -> enq; +%% method_name(2) -> pushq_bin; +%% method_name(3) -> enq_bin; +%% method_name(4) -> pushqv; +%% method_name(5) -> enqv. + +dequeue(Port, DataList, LenToGet, DeqSize) -> + io:format("Dequeuing ~p bytes, ~p byte(s) at once...", [LenToGet,DeqSize]), + compare_return(Port, DataList, LenToGet, DeqSize). + +compare_return(Port, _Data_list, 0, _Back_len) -> + 0 = bytes_queued(Port); +compare_return(Port, QueuedInPort0, Len_to_get, DeqSize) -> + case bytes_queued(Port) of + Len_to_get -> ok; + BytesInQueue -> + io:format("Len_to_get: ~p", [Len_to_get]), + io:format("Bytes in queue: ~p", [BytesInQueue]), + ?line test_server:fail() + end, + BytesToDequeue = if (DeqSize > Len_to_get) -> Len_to_get; + true -> DeqSize + end, + Dequeued = read_head(Port, BytesToDequeue), + case bin_prefix(Dequeued, QueuedInPort0) of + true -> + deq(Port, BytesToDequeue), + <<_:BytesToDequeue/binary,QueuedInPort/binary>> = QueuedInPort0, + compare_return(Port, QueuedInPort, Len_to_get - BytesToDequeue, DeqSize); + false -> + io:format("Bytes to dequeue: ~p", [BytesToDequeue]), + io:format("Dequeued: ~p", [Dequeued]), + io:format("Queued in port: ~P", [QueuedInPort0,12]), + ?t:fail() + end. + +%% bin_prefix(PrefixBinary, Binary) +%% Is PrefixBinary a prefix of Binary? + +bin_prefix(<<C:8,PreTail/binary>>, <<C:8,Tail/binary>>) -> + bin_prefix(PreTail, Tail); +bin_prefix(<<>>, _Bin) -> true; +bin_prefix(_, _) -> false. + +queue_op(Port, Method, Data) -> + [] = erlang:port_control(Port, Method, []), + Port ! {self(),{command,Data}}, + ok. + +bytes_queued(Port) -> + case erlang:port_control(Port, ?BYTES_QUEUED, []) of + <<I:32>> -> I; + Bad -> ?t:fail({bad_result,Bad}) + end. + +deq(Port, Size) -> + [] = erlang:port_control(Port, ?DEQ, <<Size:32>>). + +read_head(Port, Size) -> + erlang:port_control(Port, ?READ_HEAD, <<Size:32>>). + + +driver_unloaded(doc) -> + []; +driver_unloaded(suite) -> + []; +driver_unloaded(Config) when is_list(Config) -> + ?line process_flag(trap_exit, true), + ?line Drv = timer_drv, + ?line User = self(), + ?line Loaded = make_ref(), + ?line Die = make_ref(), + ?line Loader = spawn(fun () -> + erl_ddll:start(), + ok = load_driver(?config(data_dir, + Config), + Drv), + User ! Loaded, + receive Die -> exit(bye) end + end), + ?line receive Loaded -> ok end, + ?line Port = open_port({spawn, Drv}, []), + ?line Loader ! Die, + ?line receive + {'EXIT', Port, Reason} -> + ?line driver_unloaded = Reason + %% Reason used to be -1 + end. + + +io_ready_exit(doc) -> []; +io_ready_exit(suite) -> []; +io_ready_exit(Config) when is_list(Config) -> + ?line OTE = process_flag(trap_exit, true), + ?line Test = self(), + ?line Dgawd = spawn(fun () -> + ok = dgawd_handler:install(), + Mon = erlang:monitor(process, Test), + Test ! dgawd_handler_started, + receive + {'DOWN', Mon, _, _, _} -> ok; + stop_dgawd_handler -> ok + end, + dgawd_handler:restore(), + Test ! dgawd_handler_stopped + end), + ?line receive dgawd_handler_started -> ok end, + ?line Drv = io_ready_exit_drv, + ?line erl_ddll:start(), + ?line ok = load_driver(?config(data_dir, Config), Drv), + ?line Port = open_port({spawn, Drv}, []), + ?line case erlang:port_control(Port, 0, "") of + "ok" -> + receive + {'EXIT', Port, Reason} -> + ?line case Reason of + ready_output_driver_failure -> + ?t:format("Exited in output_ready()~n"), + ?line ok; + ready_input_driver_failure -> + ?t:format("Exited in input_ready()~n"), + ?line ok; + Error -> ?line ?t:fail(Error) + end + end, + receive after 2000 -> ok end, + ?line false = dgawd_handler:got_dgawd_report(), + ?line Dgawd ! stop_dgawd_handler, + ?line receive dgawd_handler_stopped -> ok end, + ?line process_flag(trap_exit, OTE), + ?line ok; + "nyiftos" -> + ?line process_flag(trap_exit, OTE), + ?line {skipped, "Not yet implemented for this OS"}; + Error -> + ?line process_flag(trap_exit, OTE), + ?line ?t:fail({unexpected_control_result, Error}) + end. + + +-define(CHKIO_STOP, 0). +-define(CHKIO_USE_FALLBACK_POLLSET, 1). +-define(CHKIO_BAD_FD_IN_POLLSET, 2). +-define(CHKIO_DRIVER_EVENT, 3). +-define(CHKIO_FD_CHANGE, 4). +-define(CHKIO_STEAL, 5). +-define(CHKIO_STEAL_AUX, 6). +-define(CHKIO_SMP_SELECT, 7). +-define(CHKIO_DRV_USE, 8). + +use_fallback_pollset(doc) -> []; +use_fallback_pollset(suite) -> []; +use_fallback_pollset(Config) when is_list(Config) -> + FlbkFun = fun () -> + ChkIoDuring = erlang:system_info(check_io), + case lists:keysearch(fallback_poll_set_size, + 1, + ChkIoDuring) of + {value, + {fallback_poll_set_size, N}} when N > 0 -> + ?line ok; + Error -> + ?line ?t:fail({failed_to_use_fallback, Error}) + end + end, + ?line {BckupTest, Handel, OkRes} + = case chkio_test_init(Config) of + {erts_poll_info, ChkIo} = Hndl -> + case lists:keysearch(fallback, 1, ChkIo) of + {value, {fallback, B}} when B =/= false -> + ?line {FlbkFun, Hndl, ok}; + _ -> + ?line {fun () -> ok end, + Hndl, + {comment, + "This implementation does not use " + "a fallback pollset"}} + end; + Skip -> + {fun () -> ok end, Skip, ok} + end, + ?line case chkio_test_fini(chkio_test(Handel, + ?CHKIO_USE_FALLBACK_POLLSET, + fun () -> + ?line sleep(1000), + ?line BckupTest() + end)) of + {skipped, _} = Res -> ?line Res; + _ -> ?line OkRes + end. + +bad_fd_in_pollset(doc) -> []; +bad_fd_in_pollset(suite) -> []; +bad_fd_in_pollset(Config) when is_list(Config) -> + ?line chkio_test_fini(chkio_test(chkio_test_init(Config), + ?CHKIO_BAD_FD_IN_POLLSET, + fun () -> ?line sleep(1000) end)). + +driver_event(doc) -> []; +driver_event(suite) -> []; +driver_event(Config) when is_list(Config) -> + ?line chkio_test_fini(chkio_test(chkio_test_init(Config), + ?CHKIO_DRIVER_EVENT, + fun () -> ?line sleep(1000) end)). + +fd_change(doc) -> []; +fd_change(suite) -> []; +fd_change(Config) when is_list(Config) -> + ?line chkio_test_fini(chkio_test(chkio_test_init(Config), + ?CHKIO_FD_CHANGE, + fun () -> ?line sleep(1000) end)). + +steal_control(doc) -> []; +steal_control(suite) -> []; +steal_control(Config) when is_list(Config) -> + ?line chkio_test_fini(case chkio_test_init(Config) of + {erts_poll_info, _} = Hndl -> + ?line steal_control_test(Hndl); + Skip -> + ?line Skip + end). + +steal_control_test(Hndl = {erts_poll_info, Before}) -> + ?line Port = open_chkio_port(), + ?line case erlang:port_control(Port, ?CHKIO_STEAL_AUX, "") of + [$f,$d,$s,$:| _] = FdList -> + ?line chk_chkio_port(Port), + sleep(500), + ?line chk_chkio_port(Port), + ?line Res = chkio_test(Hndl, + ?CHKIO_STEAL, + FdList, + fun () -> + ?line chk_chkio_port(Port), + ?line sleep(500), + ?line chk_chkio_port(Port) + end), + ?line case erlang:port_control(Port, ?CHKIO_STOP, "") of + "ok" -> + ?line chk_chkio_port(Port), + ?line ok; + StopErr -> + ?line chk_chkio_port(Port), + ?line ?t:fail({stop_error, StopErr}) + end, + ?line close_chkio_port(Port), + ?line Res; + [$s,$k,$i,$p,$:,$\ |Skip] -> + ?line chk_chkio_port(Port), + ?line close_chkio_port(Port), + {chkio_test_result, + {skipped, Skip}, + Before}; + StartErr -> + ?line chk_chkio_port(Port), + ?line ?t:fail({start_error, StartErr}) + end. + +chkio_test_init(Config) when is_list(Config) -> + ?line wait_until_no_pending_updates(), + ?line ChkIo = erlang:system_info(check_io), + ?line case catch lists:keysearch(name, 1, ChkIo) of + {value, {name, erts_poll}} -> + ?line ?t:format("Before test: ~p~n", [ChkIo]), + ?line Path = ?config(data_dir, Config), + ?line erl_ddll:start(), + ?line ok = load_driver(Path, 'chkio_drv'), + ?line process_flag(trap_exit, true), + ?line {erts_poll_info, ChkIo}; + _ -> + ?line {skipped, "Test written to test erts_poll() which isn't used"} + end. + + +chkio_test_fini({skipped, _} = Res) -> + Res; +chkio_test_fini({chkio_test_result, Res, Before}) -> + ?line ok = erl_ddll:unload_driver('chkio_drv'), + ?line ok = erl_ddll:stop(), + ?line wait_until_no_pending_updates(), + ?line After = erlang:system_info(check_io), + ?line ?t:format("After test: ~p~n", [After]), + ?line verify_chkio_state(Before, After), + ?line Res. + +open_chkio_port() -> + open_port({spawn, 'chkio_drv'}, []). + +close_chkio_port(Port) when is_port(Port) -> + true = erlang:port_close(Port), + receive + {'EXIT', Port, normal} -> + ok; + {'EXIT', Port, Reason} -> + ?t:fail({abnormal_port_exit, Port, Reason}); + {Port, Message} -> + ?t:fail({strange_message_from_port, Message}) + end. + +chk_chkio_port(Port) -> + receive + {'EXIT', Port, Reason} when Reason /= normal -> + ?t:fail({port_exited, Port, Reason}) + after 0 -> + ok + end. + + +chkio_test({skipped, _} = Res, _Test, _Fun) -> + ?line Res; +chkio_test({erts_poll_info, _Before} = EPI, Test, Fun) when is_integer(Test) -> + chkio_test(EPI, Test, "", Fun). + +chkio_test({skipped, _} = Res, _Test, _TestArgs, _Fun) -> + ?line Res; +chkio_test({erts_poll_info, Before}, + Test, + TestArgs, + Fun) when is_integer(Test), + is_list(TestArgs) -> + ?line Port = open_chkio_port(), + ?line case erlang:port_control(Port, Test, TestArgs) of + "ok" -> + ?line chk_chkio_port(Port), + ?line Fun(), + ?line During = erlang:system_info(check_io), + ?line erlang:display(During), + ?line 0 = erts_debug:get_internal_state(check_io_debug), + ?line ?t:format("During test: ~p~n", [During]), + ?line chk_chkio_port(Port), + ?line case erlang:port_control(Port, ?CHKIO_STOP, "") of + Res when is_list(Res) -> + ?line chk_chkio_port(Port), + ?line ?t:format("~s", [Res]), + ?line close_chkio_port(Port), + ?line Res, + ?line case Res of + [$c,$o,$m,$m,$e,$n,$t,$:,$\ |Cmnt] -> + ?line {chkio_test_result, + {comment, Cmnt}, + Before}; + _ -> + ?line {chkio_test_result, + Res, + Before} + end; + StopErr -> + ?line chk_chkio_port(Port), + ?line ?t:fail({stop_error, StopErr}) + end; + [$s,$k,$i,$p,$:,$\ |Skip] -> + ?line chk_chkio_port(Port), + ?line close_chkio_port(Port), + {chkio_test_result, + {skipped, Skip}, + Before}; + StartErr -> + ?line chk_chkio_port(Port), + ?line ?t:fail({start_error, StartErr}) + end. + +verify_chkio_state(Before, After) -> + ?line TotSetSize = lists:keysearch(total_poll_set_size, 1, Before), + ?line TotSetSize = lists:keysearch(total_poll_set_size, 1, After), + ?line case lists:keysearch(fallback, 1, Before) of + {value,{fallback,false}} -> + ?line ok; + _ -> + ?line BckupSetSize = lists:keysearch(fallback_poll_set_size, + 1, + Before), + ?line BckupSetSize = lists:keysearch(fallback_poll_set_size, + 1, + After) + end, + ?line ok. + + + +wait_until_no_pending_updates() -> + case lists:keysearch(pending_updates, 1, erlang:system_info(check_io)) of + {value, {pending_updates, 0}} -> + ok; + false -> + ok; + _ -> + receive after 10 -> ok end, + wait_until_no_pending_updates() + end. + +otp_6602(doc) -> ["Missed port lock when stealing control of fd from a " + "driver that didn't use the same lock. The lock checker " + "used to trigger on this and dump core."]; +otp_6602(suite) -> + []; +otp_6602(Config) when is_list(Config) -> + ?line {ok, Node} = start_node(Config), + ?line Done = make_ref(), + ?line Parent = self(), + ?line Tester = spawn_link(Node, + fun () -> + %% Inet driver use port locking... + {ok, S} = gen_udp:open(0), + {ok, Fd} = inet:getfd(S), + {ok, Port} = inet:port(S), + %% Steal fd (lock checker used to + %% trigger here). + {ok, _S2} = gen_udp:open(Port,[{fd,Fd}]), + Parent ! Done + end), + ?line receive Done -> ok end, + ?line unlink(Tester), + ?line stop_node(Node), + ?line ok. + +-define(EXPECTED_SYSTEM_INFO_NAMES1, + ["drv_drv_vsn", + "emu_drv_vsn", + "erts_vsn", + "otp_vsn", + "thread", + "smp"]). +-define(EXPECTED_SYSTEM_INFO_NAMES2, + (?EXPECTED_SYSTEM_INFO_NAMES1 ++ + ["async_thrs", + "sched_thrs"])). + +-define(EXPECTED_SYSTEM_INFO_NAMES, ?EXPECTED_SYSTEM_INFO_NAMES2). + +'driver_system_info_ver1.0'(doc) -> + []; +'driver_system_info_ver1.0'(suite) -> + []; +'driver_system_info_ver1.0'(Config) when is_list(Config) -> + ?line driver_system_info_test(Config, sys_info_1_0_drv). + +'driver_system_info_ver1.1'(doc) -> + []; +'driver_system_info_ver1.1'(suite) -> + []; +'driver_system_info_ver1.1'(Config) when is_list(Config) -> + ?line driver_system_info_test(Config, sys_info_1_1_drv). + +driver_system_info_current_ver(doc) -> + []; +driver_system_info_current_ver(suite) -> + []; +driver_system_info_current_ver(Config) when is_list(Config) -> + ?line driver_system_info_test(Config, sys_info_curr_drv). + +driver_system_info_test(Config, Name) -> + ?line Port = start_driver(Config, Name, false), + ?line case erlang:port_control(Port, 0, []) of + [$o,$k,$:,_ | Result] -> + ?line check_driver_system_info_result(Result); + [$e,$r,$r,$o,$r,$:,_ | Error] -> + ?line ?t:fail(Error); + Unexpected -> + ?line ?t:fail({unexpected_result, Unexpected}) + end, + ?line stop_driver(Port, Name), + ?line ok. + +check_driver_system_info_result(Result) -> + ?line ?t:format("All names: ~p~n", [?EXPECTED_SYSTEM_INFO_NAMES]), + ?line ?t:format("Result: ~p~n", [Result]), + ?line {[], Ns, DDVSN} = chk_sis(lists:map(fun (Str) -> + string:tokens(Str, "=") + end, + string:tokens(Result, " ")), + ?EXPECTED_SYSTEM_INFO_NAMES), + ?line case {DDVSN, + drv_vsn_str2tup(erlang:system_info(driver_version))} of + {DDVSN, DDVSN} -> + ?line [] = Ns; + {{1, 0}, _} -> + ?line ExpNs = lists:sort(?EXPECTED_SYSTEM_INFO_NAMES + -- ?EXPECTED_SYSTEM_INFO_NAMES1), + ?line ExpNs = lists:sort(Ns); + {{1, 1}, _} -> + ?line ExpNs = lists:sort(?EXPECTED_SYSTEM_INFO_NAMES + -- ?EXPECTED_SYSTEM_INFO_NAMES2), + ?line ExpNs = lists:sort(Ns) + end. + +chk_sis(SIs, Ns) -> + chk_sis(SIs, Ns, unknown). + +chk_sis(SIs, [], DDVSN) -> + ?line {SIs, [], DDVSN}; +chk_sis([], Ns, DDVSN) -> + ?line {[], Ns, DDVSN}; +chk_sis([[N, _] = SI| SIs], Ns, DDVSN) -> + ?line true = lists:member(N, Ns), + ?line case check_si_res(SI) of + {driver_version, NewDDVSN} -> + ?line chk_sis(SIs, lists:delete(N, Ns), NewDDVSN); + _ -> + ?line chk_sis(SIs, lists:delete(N, Ns), DDVSN) + end. + +%% Data in first version of driver_system_info() (driver version 1.0) +check_si_res(["drv_drv_vsn", Value]) -> + ?line DDVSN = drv_vsn_str2tup(Value), + ?line {Major, DMinor} = DDVSN, + ?line {Major, EMinor} = drv_vsn_str2tup(erlang:system_info(driver_version)), + ?line true = DMinor =< EMinor, + ?line {driver_version, DDVSN}; +check_si_res(["emu_drv_vsn", Value]) -> + ?line Value = erlang:system_info(driver_version); +check_si_res(["erts_vsn", Value]) -> + ?line Value = erlang:system_info(version); +check_si_res(["otp_vsn", Value]) -> + ?line Value = erlang:system_info(otp_release); +check_si_res(["thread", "true"]) -> + ?line true = erlang:system_info(threads); +check_si_res(["thread", "false"]) -> + ?line false = erlang:system_info(threads); +check_si_res(["smp", "true"]) -> + ?line true = erlang:system_info(smp_support); +check_si_res(["smp", "false"]) -> + ?line false = erlang:system_info(smp_support); + +%% Data added in second version of driver_system_info() (driver version 1.1) +check_si_res(["async_thrs", Value]) -> + ?line Value = integer_to_list(erlang:system_info(thread_pool_size)); +check_si_res(["sched_thrs", Value]) -> + ?line Value = integer_to_list(erlang:system_info(schedulers)); + +check_si_res(Unexpected) -> + ?line ?t:fail({unexpected_result, Unexpected}). + +-define(MON_OP_I_AM_IPID,1). +-define(MON_OP_MONITOR_ME,2). +-define(MON_OP_DEMONITOR_ME,3). +-define(MON_OP_MONITOR_ME_LATER,4). +-define(MON_OP_DO_DELAYED_MONITOR,5). + +driver_monitor(suite) -> + []; +driver_monitor(doc) -> + ["Test monitoring of processes from drivers"]; +driver_monitor(Config) when is_list(Config) -> + ?line Name = monitor_drv, + ?line Port = start_driver(Config, Name, false), + ?line "ok" = port_control(Port,?MON_OP_I_AM_IPID,[]), + ?line "ok" = port_control(Port,?MON_OP_MONITOR_ME,[]), + ?line "ok" = port_control(Port,?MON_OP_DEMONITOR_ME,[]), + ?line {monitors, []} = erlang:port_info(Port,monitors), + + ?line "ok:"++Id1 = port_control(Port,?MON_OP_MONITOR_ME_LATER,[]), + ?line {monitored_by, []} = process_info(self(),monitored_by), + ?line "ok" = port_control(Port,?MON_OP_DO_DELAYED_MONITOR,Id1), + ?line {monitored_by, [Port]} = process_info(self(),monitored_by), + ?line "ok" = port_control(Port,?MON_OP_DEMONITOR_ME,[]), + ?line {monitored_by, []} = process_info(self(),monitored_by), + + ?line "ok" = port_control(Port,?MON_OP_MONITOR_ME,[]), + ?line Me = self(), + ?line {Pid1,Ref1} = + spawn_monitor(fun() -> + Me ! port_control(Port,?MON_OP_MONITOR_ME,[]), + Me ! process_info(self(),monitored_by), + Me ! erlang:port_info(Port,monitors) + end), + ?line ok = receive + "ok" -> + ok + after 1000 -> + timeout + end, + ?line ok = receive + {monitored_by, L} -> + L2 = lists:sort(L), + L3 = lists:sort([Me,Port]), + case L2 of + L3 -> + ok; + _ -> + mismatch + end + after 1000 -> + timeout + end, + ?line ok = receive + {monitors, LL} -> + LL2 = lists:sort(LL), + LL3 = lists:sort([{process,Me},{process,Pid1}]), + case LL2 of + LL3 -> + ok; + _ -> + mismatch + end + after 1000 -> + timeout + end, + ?line ok = receive + {'DOWN', Ref1, process, Pid1, _} -> + ok + after 1000 -> + timeout + end, + ?line ok = receive + {monitor_fired,Port,Pid1} -> + ok + after 1000 -> + timeout + end, + ?line "ok" = port_control(Port,?MON_OP_DEMONITOR_ME,[]), + ?line {monitors,[]} = erlang:port_info(Port,monitors), + ?line {monitored_by, []} = process_info(self(),monitored_by), + + ?line "ok" = port_control(Port,?MON_OP_MONITOR_ME,[]), + ?line {Pid2,Ref2} = + spawn_monitor(fun() -> + receive go -> ok end, + Me ! port_control(Port,?MON_OP_MONITOR_ME_LATER,[]), + Me ! process_info(self(),monitored_by), + Me ! erlang:port_info(Port,monitors) + end), + ?line Pid2 ! go, + ?line {ok,Id2} = receive + "ok:"++II -> + {ok,II} + after 1000 -> + timeout + end, + ?line ok = receive + {monitored_by, [Me]} -> + ok + after 1000 -> + timeout + end, + ?line ok = receive + {monitors, [{process,Me}]} -> + ok + after 1000 -> + timeout + end, + ?line ok = receive + {'DOWN', Ref2, process, Pid2, _} -> + ok + after 1000 -> + timeout + end, + ?line "noproc" = port_control(Port,?MON_OP_DO_DELAYED_MONITOR,Id2), + ?line {monitors,[{process,Me}]} = erlang:port_info(Port,monitors), + ?line "ok" = port_control(Port,?MON_OP_DEMONITOR_ME,[]), + ?line "not_monitored" = port_control(Port,?MON_OP_DEMONITOR_ME,[]), + ?line {monitors,[]} = erlang:port_info(Port,monitors), + ?line {monitored_by, []} = process_info(self(),monitored_by), + + + ?line "ok" = port_control(Port,?MON_OP_MONITOR_ME,[]), + ?line {Pid3,Ref3} = + spawn_monitor(fun() -> + receive go -> ok end, + Me ! port_control(Port,?MON_OP_MONITOR_ME_LATER,[]), + Me ! process_info(self(),monitored_by), + Me ! erlang:port_info(Port,monitors) , + receive die -> ok end + end), + ?line Pid3 ! go, + ?line {ok,Id3} = receive + "ok:"++III -> + {ok,III} + after 1000 -> + timeout + end, + ?line ok = receive + {monitored_by, [Me]} -> + ok + after 1000 -> + timeout + end, + ?line ok = receive + {monitors, [{process,Me}]} -> + ok + after 1000 -> + timeout + end, + ?line "ok" = port_control(Port,?MON_OP_DO_DELAYED_MONITOR,Id3), + ?line LLL1 = lists:sort([{process,Me},{process,Pid3}]), + ?line {monitors,LLL2} = erlang:port_info(Port,monitors), + ?line LLL1 = lists:sort(LLL2), + ?line "ok" = port_control(Port,?MON_OP_DEMONITOR_ME,[]), + ?line {monitors,[{process,Pid3}]} = erlang:port_info(Port,monitors), + ?line Pid3 ! die, + ?line ok = receive + {'DOWN', Ref3, process, Pid3, _} -> + ok + after 1000 -> + timeout + end, + ?line "not_found" = port_control(Port,?MON_OP_DO_DELAYED_MONITOR,Id2), + ?line {monitors,[]} = erlang:port_info(Port,monitors), + ?line "not_monitored" = port_control(Port,?MON_OP_DEMONITOR_ME,[]), + ?line {monitors,[]} = erlang:port_info(Port,monitors), + ?line {monitored_by, []} = process_info(self(),monitored_by), + + ?line stop_driver(Port, Name), + ?line ok. + +ioq_exit(doc) -> []; +ioq_exit(suite) -> + [ioq_exit_ready_input, + ioq_exit_ready_output, + ioq_exit_timeout, + ioq_exit_ready_async, + ioq_exit_event, + ioq_exit_ready_input_async, + ioq_exit_ready_output_async, + ioq_exit_timeout_async, + ioq_exit_event_async]. + +-define(IOQ_EXIT_READY_INPUT, 1). +-define(IOQ_EXIT_READY_OUTPUT, 2). +-define(IOQ_EXIT_TIMEOUT, 3). +-define(IOQ_EXIT_READY_ASYNC, 4). +-define(IOQ_EXIT_EVENT, 5). +-define(IOQ_EXIT_READY_INPUT_ASYNC, 6). +-define(IOQ_EXIT_READY_OUTPUT_ASYNC, 7). +-define(IOQ_EXIT_TIMEOUT_ASYNC, 8). +-define(IOQ_EXIT_EVENT_ASYNC, 9). + +ioq_exit_test(Config, TestNo) -> + ?line Drv = ioq_exit_drv, + ?line try + begin + ?line case load_driver(?config(data_dir, Config), + Drv) of + ok -> ?line ok; + {error, permanent} -> ?line ok; + LoadError -> ?line ?t:fail({load_error, LoadError}) + end, + case open_port({spawn, Drv}, []) of + Port when is_port(Port) -> + try port_control(Port, TestNo, "") of + "ok" -> + ?line ok; + "nyiftos" -> + ?line throw({skipped, + "Not yet implemented for " + "this OS"}); + [$s,$k,$i,$p,$:,$ | Comment] -> + ?line throw({skipped, Comment}); + [$e,$r,$r,$o,$r,$:,$ | Error] -> + ?line ?t:fail(Error) + after + Port ! {self(), close}, + receive {Port, closed} -> ok end, + false = lists:member(Port, erlang:ports()), + ok + end; + Error -> + ?line ?t:fail({open_port_failed, Error}) + end + end + catch + throw:Term -> ?line Term + after + erl_ddll:unload_driver(Drv) + end. + +ioq_exit_ready_input(doc) -> []; +ioq_exit_ready_input(suite) -> []; +ioq_exit_ready_input(Config) when is_list(Config) -> + ioq_exit_test(Config, ?IOQ_EXIT_READY_INPUT). + +ioq_exit_ready_output(doc) -> []; +ioq_exit_ready_output(suite) -> []; +ioq_exit_ready_output(Config) when is_list(Config) -> + ioq_exit_test(Config, ?IOQ_EXIT_READY_OUTPUT). + +ioq_exit_timeout(doc) -> []; +ioq_exit_timeout(suite) -> []; +ioq_exit_timeout(Config) when is_list(Config) -> + ioq_exit_test(Config, ?IOQ_EXIT_TIMEOUT). + +ioq_exit_ready_async(doc) -> []; +ioq_exit_ready_async(suite) -> []; +ioq_exit_ready_async(Config) when is_list(Config) -> + ioq_exit_test(Config, ?IOQ_EXIT_READY_ASYNC). + +ioq_exit_event(doc) -> []; +ioq_exit_event(suite) -> []; +ioq_exit_event(Config) when is_list(Config) -> + ioq_exit_test(Config, ?IOQ_EXIT_EVENT). + +ioq_exit_ready_input_async(doc) -> []; +ioq_exit_ready_input_async(suite) -> []; +ioq_exit_ready_input_async(Config) when is_list(Config) -> + ioq_exit_test(Config, ?IOQ_EXIT_READY_INPUT_ASYNC). + +ioq_exit_ready_output_async(doc) -> []; +ioq_exit_ready_output_async(suite) -> []; +ioq_exit_ready_output_async(Config) when is_list(Config) -> + ioq_exit_test(Config, ?IOQ_EXIT_READY_OUTPUT_ASYNC). + +ioq_exit_timeout_async(doc) -> []; +ioq_exit_timeout_async(suite) -> []; +ioq_exit_timeout_async(Config) when is_list(Config) -> + ioq_exit_test(Config, ?IOQ_EXIT_TIMEOUT_ASYNC). + +ioq_exit_event_async(doc) -> []; +ioq_exit_event_async(suite) -> []; +ioq_exit_event_async(Config) when is_list(Config) -> + ioq_exit_test(Config, ?IOQ_EXIT_EVENT_ASYNC). + + +vsn_mismatch_test(Config, LoadResult) -> + ?line Path = ?config(data_dir, Config), + ?line DrvName = ?config(testcase, Config), + ?line LoadResult = load_driver(Path, DrvName), + ?line case LoadResult of + ok -> + ?line Port = open_port({spawn, DrvName}, []), + ?line true = is_port(Port), + ?line true = port_close(Port), + ?line ok = erl_ddll:unload_driver(DrvName); + _ -> + ?line ok + end. + +zero_extended_marker_garb_drv(doc) -> []; +zero_extended_marker_garb_drv(suite) -> []; +zero_extended_marker_garb_drv(Config) when is_list(Config) -> + vsn_mismatch_test(Config, {error, driver_incorrect_version}). + +invalid_extended_marker_drv(doc) -> []; +invalid_extended_marker_drv(suite) -> []; +invalid_extended_marker_drv(Config) when is_list(Config) -> + vsn_mismatch_test(Config, {error, driver_incorrect_version}). + +larger_major_vsn_drv(doc) -> []; +larger_major_vsn_drv(suite) -> []; +larger_major_vsn_drv(Config) when is_list(Config) -> + vsn_mismatch_test(Config, {error, driver_incorrect_version}). + +larger_minor_vsn_drv(doc) -> []; +larger_minor_vsn_drv(suite) -> []; +larger_minor_vsn_drv(Config) when is_list(Config) -> + vsn_mismatch_test(Config, {error, driver_incorrect_version}). + +smaller_major_vsn_drv(doc) -> []; +smaller_major_vsn_drv(suite) -> []; +smaller_major_vsn_drv(Config) when is_list(Config) -> + vsn_mismatch_test(Config, {error, driver_incorrect_version}). + +smaller_minor_vsn_drv(doc) -> []; +smaller_minor_vsn_drv(suite) -> []; +smaller_minor_vsn_drv(Config) when is_list(Config) -> + DrvVsnStr = erlang:system_info(driver_version), + case drv_vsn_str2tup(DrvVsnStr) of + {_, 0} -> + {skipped, + "Cannot perform test when minor driver version is 0. " + "Current driver version is " ++ DrvVsnStr ++ "."}; + _ -> + vsn_mismatch_test(Config, ok) + end. + +-define(PEEK_NONXQ_TEST, 0). +-define(PEEK_NONXQ_WAIT, 1). + +peek_non_existing_queue(doc) -> []; +peek_non_existing_queue(suite) -> []; +peek_non_existing_queue(Config) when is_list(Config) -> + ?line OTE = process_flag(trap_exit, true), + ?line Drv = peek_non_existing_queue_drv, + ?line try + begin + ?line case load_driver(?config(data_dir, Config), + Drv) of + ok -> ?line ok; + {error, permanent} -> ?line ok; + LoadError -> ?line ?t:fail({load_error, LoadError}) + end, + case open_port({spawn, Drv}, []) of + Port1 when is_port(Port1) -> + try port_control(Port1, ?PEEK_NONXQ_TEST, "") of + "ok" -> + ?line ok; + [$s,$k,$i,$p,$p,$e,$d,$:,$ | SkipReason] -> + ?line throw({skipped, SkipReason}); + [$e,$r,$r,$o,$r,$:,$ | Error1] -> + ?line ?t:fail(Error1) + after + exit(Port1, kill), + receive {'EXIT', Port1, _} -> ok end + end; + Error1 -> + ?line ?t:fail({open_port1_failed, Error1}) + end, + case open_port({spawn, Drv}, []) of + Port2 when is_port(Port2) -> + try port_control(Port2, ?PEEK_NONXQ_WAIT, "") of + "ok" -> + ?line ok; + [$e,$r,$r,$o,$r,$:,$ | Error2] -> + ?line ?t:fail(Error2) + after + receive {Port2, test_successful} -> ok end, + Port2 ! {self(), close}, + receive {Port2, closed} -> ok end + end; + Error2 -> + ?line ?t:fail({open_port2_failed, Error2}) + end + end + catch + throw:Term -> ?line Term + after + process_flag(trap_exit, OTE), + erl_ddll:unload_driver(Drv) + end. + +otp_6879(doc) -> + []; +otp_6879(suite) -> + []; +otp_6879(Config) when is_list(Config) -> + ?line Drv = 'otp_6879_drv', + ?line Parent = self(), + ?line ok = load_driver(?config(data_dir, Config), Drv), + ?line Procs = lists:map( + fun (No) -> + spawn_link( + fun () -> + case open_port({spawn, Drv}, []) of + Port when is_port(Port) -> + Res = otp_6879_call(Port, No, 10000), + erlang:port_close(Port), + Parent ! {self(), Res}; + _ -> + Parent ! {self(), + open_port_failed} + end + end) + end, + lists:seq(1,10)), + ?line lists:foreach(fun (P) -> + ?line receive + {P, ok} -> + ?line ok; + {P, Error} -> + ?line ?t:fail({P, Error}) + end + end, + Procs), + %% Also try it when input exeeds default buffer (256 bytes) + ?line Data = lists:seq(1, 1000), + ?line case open_port({spawn, Drv}, []) of + Port when is_port(Port) -> + ?line ok = otp_6879_call(Port, Data, 10), + ?line erlang:port_close(Port); + _ -> + ?line ?t:fail(open_port_failed) + end, + ?line erl_ddll:unload_driver(Drv), + ?line ok. + +otp_6879_call(_Port, _Data, 0) -> + ok; +otp_6879_call(Port, Data, N) -> + case catch erlang:port_call(Port, 0, Data) of + Data -> otp_6879_call(Port, Data, N-1); + BadData -> {mismatch, Data, BadData} + end. + +caller(doc) -> + []; +caller(suite) -> + []; +caller(Config) when is_list(Config) -> + ?line run_caller_test(Config, false), + ?line run_caller_test(Config, true). + +run_caller_test(Config, Outputv) -> + ?line Drv = 'caller_drv', + ?line Cmd = case Outputv of + true -> + ?line os:putenv("CALLER_DRV_USE_OUTPUTV", + "true"), + outputv; + false -> + ?line os:putenv("CALLER_DRV_USE_OUTPUTV", + "false"), + output + end, + ?line ok = load_driver(?config(data_dir, Config), Drv), + ?line Port = open_port({spawn, Drv}, []), + ?line true = is_port(Port), + ?line chk_caller(Port, start, self()), + ?line chk_caller(Port, + Cmd, + spawn_link( + fun () -> + port_command(Port, "") + end)), + ?line Port ! {self(), {command, ""}}, + ?line chk_caller(Port, Cmd, self()), + ?line chk_caller(Port, + control, + spawn_link( + fun () -> + port_control(Port, 0, "") + end)), + ?line chk_caller(Port, + call, + spawn_link( + fun () -> + erlang:port_call(Port, 0, "") + end)), + ?line true = port_close(Port), + ?line erl_ddll:unload_driver(Drv), + ?line ok. + +chk_caller(Port, Callback, ExpectedCaller) -> + receive + {caller, Port, Callback, Caller} -> + ExpectedCaller = Caller + end. + +many_events(suite) -> + []; +many_events(doc) -> + ["Check that many simultaneously signalled events work (win32)"]; +many_events(Config) when is_list(Config) -> + ?line Name = 'many_events_drv', + ?line Port = start_driver(Config, Name, false), + Number = "1000", + Port ! {self(), {command, Number}}, + receive + {Port, {data,Number}} -> + ?line receive %% Just to make sure the emulator does not crash + %% after this case is run (if faulty) + after 2000 -> + ok + end + after 1000 -> + ?line exit(the_driver_does_not_respond) + end, + ?line stop_driver(Port, Name), + ?line ok. + + +missing_callbacks(doc) -> + []; +missing_callbacks(suite) -> + []; +missing_callbacks(Config) when is_list(Config) -> + ?line Name = 'missing_callback_drv', + ?line Port = start_driver(Config, Name, false), + + ?line Port ! {self(), {command, "tjenix"}}, + ?line true = erlang:port_command(Port, "halloj"), + ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(Port, 4711, "mors")), + ?line {'EXIT', {badarg, _}} = (catch erlang:port_call(Port, 17, "hej")), + + ?line %% Give the (non-existing) ready_output(), ready_input(), event(), + ?line %% and timeout() some time to be called. + ?line receive after 1000 -> ok end, + + ?line stop_driver(Port, Name), + ?line ok. + +smp_select(doc) -> + ["Test concurrent calls to driver_select."]; +smp_select(suite) -> + []; +smp_select(Config) when is_list(Config) -> + case os:type() of + {win32,_} -> {skipped, "Test not implemented for this OS"}; + _ -> smp_select0(Config) + end. + +smp_select0(Config) -> + ?line DrvName = 'chkio_drv', + Path = ?config(data_dir, Config), + erl_ddll:start(), + ?line ok = load_driver(Path, DrvName), + Master = self(), + ProcFun = fun()-> io:format("Worker ~p starting\n",[self()]), + ?line Port = open_port({spawn, DrvName}, []), + smp_select_loop(Port, 100000), + sleep(500), % wait for driver to handle pending events + ?line true = erlang:port_close(Port), + Master ! {ok,self()}, + io:format("Worker ~p finished\n",[self()]) + end, + ?line Pids = lists:map(fun(_) -> spawn_link(ProcFun) end, + lists:seq(1,4)), + TimeoutMsg = make_ref(), + {ok,TRef} = timer:send_after(5*1000, TimeoutMsg), % Limit test duration on slow machines + smp_select_wait(Pids, TimeoutMsg), + timer:cancel(TRef), + ?line ok = erl_ddll:unload_driver(DrvName), + ?line ok = erl_ddll:stop(), + ok. + +smp_select_loop(_, 0) -> + ok; +smp_select_loop(Port, N) -> + ?line "ok" = erlang:port_control(Port, ?CHKIO_SMP_SELECT, []), + receive + stop -> + io:format("Worker ~p stopped with ~p laps left\n",[self(), N]), + ok + after 0 -> + smp_select_loop(Port, N-1) + end. + +smp_select_wait([], _) -> + ok; +smp_select_wait(Pids, TimeoutMsg) -> + receive + {ok,Pid} when is_pid(Pid) -> + smp_select_wait(lists:delete(Pid,Pids), TimeoutMsg); + TimeoutMsg -> + lists:foreach(fun(Pid)-> Pid ! stop end, + Pids), + smp_select_wait(Pids, TimeoutMsg) + end. + + +driver_select_use(doc) -> + ["Test driver_select() with new ERL_DRV_USE flag."]; +driver_select_use(suite) -> + []; +driver_select_use(Config) when is_list(Config) -> + case os:type() of + {win32,_} -> {skipped, "Test not implemented for this OS"}; + _ -> driver_select_use0(Config) + end. + +driver_select_use0(Config) -> + ?line DrvName = 'chkio_drv', + Path = ?config(data_dir, Config), + erl_ddll:start(), + ?line ok = load_driver(Path, DrvName), + ?line Port = open_port({spawn, DrvName}, []), + ?line "ok" = erlang:port_control(Port, ?CHKIO_DRV_USE, []), + ?line {Port,{data,"TheEnd"}} = receive Msg -> Msg + after 10000 -> timeout end, + ?line true = erlang:port_close(Port), + ?line ok = erl_ddll:unload_driver(DrvName), + ?line ok = erl_ddll:stop(), + ok. + +thread_mseg_alloc_cache_clean(Config) when is_list(Config) -> + case {erlang:system_info(threads), + erlang:system_info({allocator,mseg_alloc}), + driver_alloc_sbct()} of + {_, false, _} -> + ?line {skipped, "No mseg_alloc"}; + {false, _, _} -> + ?line {skipped, "No threads"}; + {_, _, false} -> + ?line {skipped, "driver_alloc() not using the alloc_util framework"}; + {_, _, SBCT} when is_integer(SBCT), SBCT > 10*1024*1024 -> + ?line {skipped, "driver_alloc() using too large single block threshold"}; + {_, _, 0} -> + ?line {skipped, "driver_alloc() using too low single block threshold"}; + {true, MsegAllocInfo, SBCT} -> + ?line DrvName = 'thr_alloc_drv', + ?line Path = ?config(data_dir, Config), + ?line erl_ddll:start(), + ?line ok = load_driver(Path, DrvName), + ?line Port = open_port({spawn, DrvName}, []), + ?line CCI = mseg_alloc_cci(MsegAllocInfo), + ?line ?t:format("CCI = ~p~n", [CCI]), + ?line CCC = mseg_alloc_ccc(), + ?line ?t:format("CCC = ~p~n", [CCC]), + ?line thread_mseg_alloc_cache_clean_test(Port, + 10, + CCI, + SBCT+100), + ?line true = erlang:port_close(Port), + ?line ok = erl_ddll:unload_driver(DrvName), + ?line ok = erl_ddll:stop(), + ?line ok + end. + +mseg_alloc_cci(MsegAllocInfo) -> + ?line {value,{options, OL}} + = lists:keysearch(options, 1, MsegAllocInfo), + ?line {value,{cci,CCI}} = lists:keysearch(cci,1,OL), + ?line CCI. + +mseg_alloc_ccc() -> + mseg_alloc_ccc(erlang:system_info({allocator,mseg_alloc})). + +mseg_alloc_ccc(MsegAllocInfo) -> + ?line {value,{calls, CL}} + = lists:keysearch(calls, 1, MsegAllocInfo), + ?line {value,{mseg_check_cache, GigaCCC, CCC}} + = lists:keysearch(mseg_check_cache, 1, CL), + ?line GigaCCC*1000000000 + CCC. + +mseg_alloc_cached_segments() -> + mseg_alloc_cached_segments(erlang:system_info({allocator,mseg_alloc})). + +mseg_alloc_cached_segments(MsegAllocInfo) -> + ?line {value,{status, SL}} + = lists:keysearch(status, 1, MsegAllocInfo), + ?line {value,{cached_segments, CS}} + = lists:keysearch(cached_segments, 1, SL), + ?line CS. + +driver_alloc_sbct() -> + {_, _, _, As} = erlang:system_info(allocator), + case lists:keysearch(driver_alloc, 1, As) of + {value,{driver_alloc,DAOPTs}} -> + case lists:keysearch(sbct, 1, DAOPTs) of + {value,{sbct,SBCT}} -> + SBCT; + _ -> + false + end; + _ -> + false + end. + +thread_mseg_alloc_cache_clean_test(_Port, 0, _CCI, _Size) -> + ?line ok; +thread_mseg_alloc_cache_clean_test(Port, N, CCI, Size) -> + ?line wait_until(fun () -> 0 == mseg_alloc_cached_segments() end), + ?line receive after CCI+500 -> ok end, + ?line OCCC = mseg_alloc_ccc(), + ?line "ok" = erlang:port_control(Port, 0, integer_to_list(Size)), + ?line receive after CCI+500 -> ok end, + ?line CCC = mseg_alloc_ccc(), + ?line ?t:format("CCC = ~p~n", [CCC]), + ?line true = CCC > OCCC, + ?line thread_mseg_alloc_cache_clean_test(Port, N-1, CCI, Size). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Utilities +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +wait_until(Fun) -> + case Fun() of + true -> ok; + false -> + receive after 100 -> ok end, + wait_until(Fun) + end. + +drv_vsn_str2tup(Str) -> + [Major, Minor] = string:tokens(Str, "."), + {list_to_integer(Major), list_to_integer(Minor)}. + +%% Build port data from a template. + +build_data({bin,Size}) -> build_binary(Size); +build_data({list,Size}) -> build_list(Size); +build_data(int) -> random_char(); +build_data([]) -> []; +build_data([H|T]) -> [build_data(H)|build_data(T)]. + +%% Transform all binaries in a term. + +transform_bins(_Transform, []) -> []; +transform_bins(Transform, [H|T]) -> + [transform_bins(Transform, H)|transform_bins(Transform, T)]; +transform_bins(Transform, Tuple) when is_tuple(Tuple) -> + list_to_tuple([transform_bins(Transform, E) || E <- tuple_to_list(Tuple)]); +transform_bins(Transform, Bin) when is_binary(Bin) -> + Transform(Bin); +transform_bins(_Transform, Other) -> Other. + + +%% Convert all binaries in a term to sub binaries. + +make_sub_binaries(Term) -> + MakeSub = fun(Bin0) -> + Bin1 = <<243:8,0:3,Bin0/binary,31:5,19:8>>, + Sz = size(Bin0), + <<243:8,0:3,Bin:Sz/binary,31:5,19:8>> = id(Bin1), + Bin + end, + transform_bins(MakeSub, Term). + +id(I) -> I. + +%% Convert all binaries in a term to refc binaries. + +make_refc_binaries(Term) -> + F = fun(B0) -> list_to_binary([build_binary(?heap_binary_size+1),B0]) end, + transform_bins(F, Term). + +build_binary(Elements) -> + list_to_binary(build_list(Elements)). + +build_list(Elements) -> build_list(Elements, []). + +build_list(0, Acc) -> Acc; +build_list(Elements, Acc) -> build_list(Elements-1, [random_char()|Acc]). + + +%% Convert all binaries in a list to writable binaries. + +make_writable_binaries(Term) -> + transform_bins(fun(Bin) -> <<Bin/binary,1,2,3>> end, Term). + +append_to_writable_binaries(Term) -> + transform_bins(fun(Bin) -> <<Bin/binary,0:(64*1024*8)>> end, Term). + +random_char() -> + uniform(256) - 1. + +uniform(N) -> + case get(random_seed) of + undefined -> + {X, Y, Z} = time(), + random:seed(X, Y, Z); + _ -> + ok + end, + random:uniform(N). + +%% return millisecs from statistics source +erl_millisecs() -> + {Ms, S, Us} = erlang:now(), + Ms * 1000000000 + S * 1000 + Us / 1000. + +erl_millisecs({Ms,S,Us}) -> + Ms * 1000000000 + S * 1000 + Us / 1000. + +%% Start/stop drivers. +start_driver(Config, Name, Binary) -> + Path = ?config(data_dir, Config), + erl_ddll:start(), + + %% Load the driver + ok = load_driver(Path, Name), + + %% open port. + case Binary of + true -> + open_port({spawn, Name}, [binary]); + false -> + open_port({spawn, Name}, []) + end. + +stop_driver(Port, Name) -> + ?line true = erlang:port_close(Port), + receive + {Port,Message} -> + ?t:fail({strange_message_from_port,Message}) + after 0 -> + ok + end, + + %% Unload the driver. + ok = erl_ddll:unload_driver(Name), + ?line ok = erl_ddll:stop(). + +load_driver(Dir, Driver) -> + case erl_ddll:load_driver(Dir, Driver) of + ok -> ok; + {error, Error} = Res -> + io:format("~s\n", [erl_ddll:format_error(Error)]), + Res + end. + +sleep() -> + receive after infinity -> ok end. + +sleep(infinity) -> + sleep(); +sleep(Ms) when is_integer(Ms), Ms >= 0 -> + receive after Ms -> ok end. + + +start_node(Config) when is_list(Config) -> + ?line Pa = filename:dirname(code:which(?MODULE)), + ?line {A, B, C} = now(), + ?line Name = list_to_atom(atom_to_list(?MODULE) + ++ "-" + ++ atom_to_list(?config(testcase, Config)) + ++ "-" + ++ integer_to_list(A) + ++ "-" + ++ integer_to_list(B) + ++ "-" + ++ integer_to_list(C)), + ?line ?t:start_node(Name, slave, [{args, "-pa "++Pa}]). + +stop_node(Node) -> + ?t:stop_node(Node). diff --git a/erts/emulator/test/driver_SUITE_data/Makefile.src b/erts/emulator/test/driver_SUITE_data/Makefile.src new file mode 100644 index 0000000000..4ac7987d2f --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/Makefile.src @@ -0,0 +1,33 @@ + +MISC_DRVS = outputv_drv@dll@ \ + timer_drv@dll@ \ + queue_drv@dll@ \ + io_ready_exit_drv@dll@ \ + chkio_drv@dll@ \ + monitor_drv@dll@ \ + ioq_exit_drv@dll@ \ + peek_non_existing_queue_drv@dll@ \ + otp_6879_drv@dll@ \ + caller_drv@dll@ \ + many_events_drv@dll@ \ + missing_callback_drv@dll@ \ + thr_alloc_drv@dll@ + +SYS_INFO_DRVS = sys_info_1_0_drv@dll@ \ + sys_info_1_1_drv@dll@ \ + sys_info_curr_drv@dll@ + +VSN_MISMATCH_DRVS = zero_extended_marker_garb_drv@dll@ \ + invalid_extended_marker_drv@dll@ \ + larger_major_vsn_drv@dll@ \ + larger_minor_vsn_drv@dll@ \ + smaller_major_vsn_drv@dll@ \ + smaller_minor_vsn_drv@dll@ + +all: $(MISC_DRVS) $(SYS_INFO_DRVS) $(VSN_MISMATCH_DRVS) + +@SHLIB_RULES@ + +$(SYS_INFO_DRVS): sys_info_drv_impl.h sys_info_drv_impl.c +$(VSN_MISMATCH_DRVS): vsn_mismatch_drv_impl.c + diff --git a/erts/emulator/test/driver_SUITE_data/caller_drv.c b/erts/emulator/test/driver_SUITE_data/caller_drv.c new file mode 100644 index 0000000000..a78d51966f --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/caller_drv.c @@ -0,0 +1,134 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include <stdlib.h> +#include <string.h> +#include "erl_driver.h" + +static ErlDrvData start(ErlDrvPort port, + char *command); +static void output(ErlDrvData drv_data, + char *buf, int len); +static void outputv(ErlDrvData drv_data, + ErlIOVec *ev); +static int control(ErlDrvData drv_data, + unsigned int command, char *buf, + int len, char **rbuf, int rlen); +static int call(ErlDrvData drv_data, + unsigned int command, + char *buf, int len, + char **rbuf, int rlen, + unsigned int *flags); + +static ErlDrvEntry caller_drv_entry = { + NULL /* init */, + start, + NULL /* stop */, + output, + NULL /* ready_input */, + NULL /* ready_output */, + "caller_drv", + NULL /* finish */, + NULL /* handle */, + control, + NULL /* timeout */, + outputv, + NULL /* ready_async */, + NULL /* flush */, + call, + NULL /* event */, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + ERL_DRV_FLAG_USE_PORT_LOCKING, + NULL /* handle2 */, + NULL /* handle_monitor */ +}; + +DRIVER_INIT(caller_drv) +{ + char buf[10]; + size_t bufsz = sizeof(buf); + char *use_outputv; + use_outputv = (erl_drv_getenv("CALLER_DRV_USE_OUTPUTV", buf, &bufsz) == 0 + ? buf + : "false"); + if (strcmp(use_outputv, "true") != 0) + caller_drv_entry.outputv = NULL; + return &caller_drv_entry; +} + +void +send_caller(ErlDrvData drv_data, char *func) +{ + int res; + ErlDrvPort port = (ErlDrvPort) drv_data; + ErlDrvTermData msg[] = { + ERL_DRV_ATOM, driver_mk_atom("caller"), + ERL_DRV_PORT, driver_mk_port(port), + ERL_DRV_ATOM, driver_mk_atom(func), + ERL_DRV_PID, driver_caller(port), + ERL_DRV_TUPLE, (ErlDrvTermData) 4 + }; + res = driver_output_term(port, msg, sizeof(msg)/sizeof(ErlDrvTermData)); + if (res <= 0) + driver_failure_atom(port, "driver_output_term failed"); +} + +static ErlDrvData +start(ErlDrvPort port, char *command) +{ + send_caller((ErlDrvData) port, "start"); + return (ErlDrvData) port; +} + +static void +output(ErlDrvData drv_data, char *buf, int len) +{ + send_caller(drv_data, "output"); +} + +static void +outputv(ErlDrvData drv_data, ErlIOVec *ev) +{ + send_caller(drv_data, "outputv"); +} + +static int +control(ErlDrvData drv_data, + unsigned int command, char *buf, + int len, char **rbuf, int rlen) +{ + send_caller(drv_data, "control"); + return 0; +} + +static int +call(ErlDrvData drv_data, + unsigned int command, + char *buf, int len, + char **rbuf, int rlen, + unsigned int *flags) +{ + /* echo call */ + if (len > rlen) + *rbuf = driver_alloc(len); + memcpy((void *) *rbuf, (void *) buf, len); + send_caller(drv_data, "call"); + return len; +} diff --git a/erts/emulator/test/driver_SUITE_data/chkio_drv.c b/erts/emulator/test/driver_SUITE_data/chkio_drv.c new file mode 100644 index 0000000000..9e1e5e72c2 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/chkio_drv.c @@ -0,0 +1,1575 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#ifndef UNIX +#if !defined(__WIN32__) && !defined(_OSE_) && !defined(VXWORKS) +#define UNIX 1 +#endif +#endif + +#ifdef UNIX +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> /* rand */ +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#ifdef HAVE_POLL_H +# include <poll.h> +#endif +#endif /* UNIX */ + +#include "erl_driver.h" + +#define CHKIO_STOP 0 +#define CHKIO_USE_FALLBACK_POLLSET 1 +#define CHKIO_BAD_FD_IN_POLLSET 2 +#define CHKIO_DRIVER_EVENT 3 +#define CHKIO_FD_CHANGE 4 +#define CHKIO_STEAL 5 +#define CHKIO_STEAL_AUX 6 +#define CHKIO_SMP_SELECT 7 +#define CHKIO_DRV_USE 8 + +#define CHKIO_FALLBACK_FDS 10 + +#define TRACEF(x) /*erts_printf x*/ + +#ifdef UNIX +typedef struct { + int fd; + int cnt; +} ChkioFallbackFd; + +typedef struct { + ChkioFallbackFd dev_null[CHKIO_FALLBACK_FDS]; + ChkioFallbackFd dev_zero[CHKIO_FALLBACK_FDS]; + ChkioFallbackFd pipe_in[CHKIO_FALLBACK_FDS]; + ChkioFallbackFd pipe_out[CHKIO_FALLBACK_FDS]; +} ChkioFallbackData; + +typedef struct { + int in_fd; + struct erl_drv_event_data in_data; + int in_ok; + int out_fd; + struct erl_drv_event_data out_data; + int out_ok; +} ChkioDriverEvent; + +typedef struct { + int fds[2]; + int same_fd; +} ChkioFdChange; + +typedef struct { + int fds[2]; +} ChkioBadFdInPollset; + +typedef struct { + int driver_select_fds[2]; + int driver_event_fds[2]; + struct erl_drv_event_data event_data[2]; +} ChkioSteal; + +typedef struct { + int driver_select_fds[2]; + int driver_event_fds[2]; + struct erl_drv_event_data event_data[2]; +} ChkioStealAux; + + +typedef struct chkio_smp_select { + struct chkio_smp_select* next; + int read_fd; + int write_fd; + int next_read; + int next_write; + enum {Closed, Opened, Selected, Waiting} state; + int wasSelected; + unsigned rand_state; +}ChkioSmpSelect; + +ChkioSmpSelect* smp_pipes; +unsigned smp_pipes_cnt; +ErlDrvMutex* smp_pipes_mtx; + +typedef struct { + int script_line; + int fd_in; + int fd_out; + int fd_pipe[2]; + volatile int fd_stop_select; + int timeouts_left; + void* expected_callback; + int expected_fd; +}ChkioDrvUse; +static ChkioDrvUse drv_use_singleton; + +typedef struct { + ErlDrvPort port; + ErlDrvTermData id; + int test; + void *test_data; +} ChkioDrvData; + + +#endif /* UNIX */ + +static int chkio_drv_init(void); +static void chkio_drv_finish(void); +static ErlDrvData chkio_drv_start(ErlDrvPort, char *); +static void chkio_drv_stop(ErlDrvData); +static void chkio_drv_ready_input(ErlDrvData, ErlDrvEvent); +static void chkio_drv_ready_output(ErlDrvData, ErlDrvEvent); +static void chkio_drv_ready_event(ErlDrvData, ErlDrvEvent, ErlDrvEventData); +static int chkio_drv_control(ErlDrvData, unsigned int, + char *, int, char **, int); +static void chkio_drv_timeout(ErlDrvData); +static void chkio_drv_stop_select(ErlDrvEvent, void*); + + +static ErlDrvEntry chkio_drv_entry = { + chkio_drv_init, + chkio_drv_start, + chkio_drv_stop, + NULL, /* output */ + chkio_drv_ready_input, + chkio_drv_ready_output, + "chkio_drv", + chkio_drv_finish, + NULL, /* handle */ + chkio_drv_control, + chkio_drv_timeout, + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, /* flush */ + NULL, /* call */ + chkio_drv_ready_event, + + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + ERL_DRV_FLAG_USE_PORT_LOCKING, + NULL,/* void *handle2 */ + NULL,/* process_exit */ + chkio_drv_stop_select +}; + + +#ifdef UNIX + +static void chkio_drv_use(ChkioDrvData *cddp, void* callback); + +static void +stop_use_fallback_pollset(ChkioDrvData *cddp) +{ + int i; + ChkioFallbackData *cbdp = (ChkioFallbackData *) cddp->test_data; + if (cbdp) { + for (i = 0; i < CHKIO_FALLBACK_FDS; i++) { + if (cbdp->dev_null[i].fd >= 0) { + if (driver_select(cddp->port, + (ErlDrvEvent) cbdp->dev_null[i].fd, + DO_WRITE, + 0) != 0) { + fprintf(stderr, + "%s:%d: Failed to deselect dev_null fd=%d\n", + __FILE__, __LINE__, cbdp->dev_null[i].fd); + abort(); + } + close(cbdp->dev_null[i].fd); + } + if (cbdp->dev_zero[i].fd >= 0) { + if (driver_select(cddp->port, + (ErlDrvEvent) cbdp->dev_zero[i].fd, + DO_READ, + 0) != 0) { + fprintf(stderr, + "%s:%d: Failed to deselct dev_zero fd=%d\n", + __FILE__, __LINE__, cbdp->dev_zero[i].fd); + abort(); + } + close(cbdp->dev_zero[i].fd); + } + if (cbdp->pipe_in[i].fd >= 0) { + if (driver_select(cddp->port, + (ErlDrvEvent) cbdp->pipe_in[i].fd, + DO_READ, + 0) != 0) { + fprintf(stderr, + "%s:%d: Failed to deselect pipe_in fd=%d\n", + __FILE__, __LINE__, cbdp->pipe_in[i].fd); + abort(); + } + close(cbdp->pipe_in[i].fd); + } + if (cbdp->pipe_out[i].fd >= 0) { + if (driver_select(cddp->port, + (ErlDrvEvent) cbdp->pipe_out[i].fd, + DO_WRITE, + 0) != 0) { + fprintf(stderr, + "%s:%d: Failed to deselect pipe_out fd=%d\n", + __FILE__, __LINE__, cbdp->pipe_out[i].fd); + abort(); + } + close(cbdp->pipe_out[i].fd); + } + } + driver_free((void *) cbdp); + cddp->test_data = NULL; + } + cddp->test = CHKIO_STOP; +} + +static void +stop_driver_event(ChkioDrvData *cddp) +{ + if (cddp->test_data) { + ChkioDriverEvent *cdep = cddp->test_data; + cddp->test_data = NULL; + + if (cdep->in_fd >= 0) { + driver_event(cddp->port, (ErlDrvEvent) cdep->in_fd, NULL); + close(cdep->in_fd); + } + if (cdep->out_fd >= 0) { + driver_event(cddp->port, (ErlDrvEvent) cdep->out_fd, NULL); + close(cdep->out_fd); + } + driver_free(cdep); + } +} + +static void +stop_fd_change(ChkioDrvData *cddp) +{ + if (cddp->test_data) { + ChkioFdChange *cfcp = (ChkioFdChange *) cddp->test_data; + cddp->test_data = NULL; + driver_cancel_timer(cddp->port); + if (cfcp->fds[0] >= 0) { + driver_select(cddp->port, (ErlDrvEvent) cfcp->fds[0], DO_READ, 0); + close(cfcp->fds[0]); + close(cfcp->fds[1]); + } + driver_free((void *) cfcp); + } +} + +static void +stop_bad_fd_in_pollset(ChkioDrvData *cddp) +{ + if (cddp->test_data) { + ChkioBadFdInPollset *bfipp = (ChkioBadFdInPollset *) cddp->test_data; + cddp->test_data = NULL; + driver_select(cddp->port, (ErlDrvEvent) bfipp->fds[0], DO_WRITE, 0); + driver_select(cddp->port, (ErlDrvEvent) bfipp->fds[1], DO_READ, 0); + driver_free((void *) bfipp); + } +} + +static void +stop_steal(ChkioDrvData *cddp) +{ + if (cddp->test_data) { + ChkioSteal *csp = cddp->test_data; + cddp->test_data = NULL; + if (csp->driver_select_fds[0] >= 0) + driver_select(cddp->port, + (ErlDrvEvent) csp->driver_select_fds[0], + DO_READ, + 0); + if (csp->driver_select_fds[1] >= 0) + driver_select(cddp->port, + (ErlDrvEvent) csp->driver_select_fds[1], + DO_WRITE, + 0); + if (csp->driver_event_fds[0] >= 0) + driver_event(cddp->port, + (ErlDrvEvent) csp->driver_event_fds[0], + NULL); + if (csp->driver_event_fds[1] >= 0) + driver_event(cddp->port, + (ErlDrvEvent) csp->driver_event_fds[1], + NULL); + driver_free(csp); + } +} + +static void +stop_steal_aux(ChkioDrvData *cddp) +{ + if (cddp->test_data) { + ChkioStealAux *csap = cddp->test_data; + cddp->test_data = NULL; + if (csap->driver_select_fds[0] >= 0) + close(csap->driver_select_fds[0]); + if (csap->driver_select_fds[1] >= 0) + close(csap->driver_select_fds[1]); + if (csap->driver_event_fds[0] >= 0) + close(csap->driver_event_fds[0]); + if (csap->driver_event_fds[1] >= 0) + close(csap->driver_event_fds[1]); + driver_free(csap); + } +} + +static void free_smp_select(ChkioSmpSelect* pip, ErlDrvPort port) +{ + switch (pip->state) { + case Waiting: { + int word; + fprintf(stderr, "Closing pipe in state Waiting. Event lost?\n"); + for (;;) { + int bytes = read(pip->read_fd, &word, sizeof(word)); + if (bytes != sizeof(word)) { + if (bytes != 0) { + fprintf(stderr, "Failed to read from pipe, bytes=%d, errno=%d\n", bytes, errno); + } + break; + } + fprintf(stderr, "Read from pipe: %d\n", word); + } + abort(); + } + case Selected: + driver_select(port, (ErlDrvEvent)pip->read_fd, DO_READ, 0); + /*fall through*/ + case Opened: + close(pip->read_fd); + close(pip->write_fd); + pip->state = Closed; + break; + } + driver_free(pip); +} + +static void +stop_smp_select(ChkioDrvData *cddp) +{ + ChkioSmpSelect* pip = (ChkioSmpSelect*)cddp->test_data; + if (pip) free_smp_select(pip, cddp->port); + erl_drv_mutex_lock(smp_pipes_mtx); + if (smp_pipes_cnt > 0 && --smp_pipes_cnt == 0) { + while (smp_pipes) { + ChkioSmpSelect* next = smp_pipes->next; + free_smp_select(smp_pipes, cddp->port); + smp_pipes = next; + } + } + erl_drv_mutex_unlock(smp_pipes_mtx); +} + +#endif /* UNIX */ + +/* ------------------------------------------------------------------------- +** Entry functions +**/ + +DRIVER_INIT(chkio_drv) +{ + return &chkio_drv_entry; +} + + +static int +chkio_drv_init(void) +{ +#ifdef UNIX + smp_pipes_mtx = erl_drv_mutex_create("smp_pipes_mtx"); +#endif + return 0; +} + +static void +chkio_drv_finish(void) +{ +#ifdef UNIX + erl_drv_mutex_destroy(smp_pipes_mtx); +#endif +} + + +static ErlDrvData +chkio_drv_start(ErlDrvPort port, char *command) +{ +#ifndef UNIX + return NULL; +#else + ChkioDrvData *cddp = driver_alloc(sizeof(ChkioDrvData)); + if (!cddp) { + errno = ENOMEM; + return ERL_DRV_ERROR_ERRNO; + } + cddp->port = port; + cddp->id = driver_mk_port(port); + cddp->test = CHKIO_STOP; + cddp->test_data = NULL; + return (ErlDrvData) cddp; +#endif +} + +static void +chkio_drv_stop(ErlDrvData drv_data) { +#ifdef UNIX + int fd; + ChkioDrvData *cddp = (ChkioDrvData *) drv_data; + + switch (cddp->test) { + case CHKIO_STOP: + break; + case CHKIO_USE_FALLBACK_POLLSET: + stop_use_fallback_pollset(cddp); + break; + case CHKIO_BAD_FD_IN_POLLSET: + stop_bad_fd_in_pollset(cddp); + break; + case CHKIO_DRIVER_EVENT: + stop_driver_event(cddp); + break; + case CHKIO_FD_CHANGE: + stop_fd_change(cddp); + break; + case CHKIO_STEAL: + stop_steal(cddp); + break; + case CHKIO_STEAL_AUX: + stop_steal_aux(cddp); + break; + case CHKIO_SMP_SELECT: + stop_smp_select(cddp); + break; + case CHKIO_DRV_USE: + chkio_drv_use(cddp, chkio_drv_stop); + break; + default: + fprintf(stderr, "%s:%d: Invalid state\n", __FILE__, __LINE__); + abort(); + break; + } + cddp->test = CHKIO_STOP; + + /* Make sure erts_poll() will handle update requests soon */ + fd = open("/dev/null", O_WRONLY); + if (fd < 0) { + fprintf(stderr, "%s:%d: Failed to open /dev/null\n", + __FILE__, __LINE__); + } + driver_select(cddp->port, (ErlDrvEvent) fd, DO_WRITE, 1); + driver_select(cddp->port, (ErlDrvEvent) fd, DO_WRITE, 0); + close(fd); + + + driver_free((void *) cddp); + +#endif +} + + +static void +chkio_drv_ready_output(ErlDrvData drv_data, ErlDrvEvent event) +{ +#ifdef UNIX + ChkioDrvData *cddp = (ChkioDrvData *) drv_data; + int fd = (int) event; + + switch (cddp->test) { + case CHKIO_USE_FALLBACK_POLLSET: { + int i; + int fd_found = 0; + ChkioFallbackData *cbdp = (ChkioFallbackData *) cddp->test_data; + for (i = 0; i < CHKIO_FALLBACK_FDS; i++) { + if (cbdp->dev_null[i].fd == fd) { + cbdp->dev_null[i].cnt++; + fd_found = 1; + break; + } + if (cbdp->pipe_out[i].fd == fd) { + cbdp->pipe_out[i].cnt++; + fd_found = 1; + break; + } + } + if (!fd_found) + driver_failure_atom(cddp->port, "output_fd_not_found"); + break; + } + case CHKIO_STEAL: + break; + case CHKIO_STEAL_AUX: + break; + case CHKIO_DRV_USE: + chkio_drv_use(cddp, chkio_drv_ready_output); + break; + default: + driver_failure_atom(cddp->port, "unexpected_ready_output"); + break; + } +#endif +} + +static void +chkio_drv_ready_input(ErlDrvData drv_data, ErlDrvEvent event) +{ +#ifdef UNIX + ChkioDrvData *cddp = (ChkioDrvData *) drv_data; + int fd = (int) event; + + switch (cddp->test) { + case CHKIO_USE_FALLBACK_POLLSET: { + int i; + int fd_found = 0; + ChkioFallbackData *cbdp = (ChkioFallbackData *) cddp->test_data; + for (i = 0; i < CHKIO_FALLBACK_FDS; i++) { + if (cbdp->dev_zero[i].fd == fd) { + cbdp->dev_zero[i].cnt++; + fd_found = 1; + break; + } + if (cbdp->pipe_in[i].fd == fd) { + cbdp->pipe_in[i].cnt++; + fd_found = 1; + break; + } + } + if (!fd_found) + driver_failure_atom(cddp->port, "input_fd_not_found"); + break; + } + case CHKIO_STEAL: + break; + case CHKIO_STEAL_AUX: + break; + case CHKIO_SMP_SELECT: { + ChkioSmpSelect* pip = (ChkioSmpSelect*) cddp->test_data; + int word=123456, bytes; + unsigned inPipe, n; + if (pip == NULL) { + printf("Read event on uninitiated pipe %d\n", fd); + abort(); + } + if (pip->state != Selected && pip->state != Waiting) { + printf("Read event on pipe in strange state %d\n", pip->state); + abort(); + } + + TRACEF(("Got read event on fd=%d, state=%d\n", fd, pip->state)); + + inPipe = (pip->next_write - pip->next_read); + if (inPipe == 0) { + bytes = read(pip->read_fd, &word, sizeof(word)); + printf("Unexpected empty pipe, expected %u -> %u, bytes=%d, word=%d\n", + pip->next_read, pip->next_write-1, bytes, word); + abort(); + } + + n = rand_r(&pip->rand_state) % (inPipe*4); + if (n > inPipe) n = inPipe; + TRACEF(("Read %u of %u words in pipe\n", n, inPipe)); + for (; n; n--) { + bytes = read(pip->read_fd, &word, sizeof(word)); + if (bytes != sizeof(word)) { + printf("Failed to read from pipe, ret=%u errno=%d\n", bytes, errno); + abort(); + } + if (word != pip->next_read) { + printf("Unexpected word in pipe %d, expected %d\n", word, pip->next_read); + abort(); + } + TRACEF(("Read %d from fd=%d\n", word, fd)); + pip->next_read++; + } + pip->state = Selected; /* not Waiting anymore */ + break; + } + case CHKIO_DRV_USE: + chkio_drv_use(cddp, chkio_drv_ready_input); + break; + default: + driver_failure_atom(cddp->port, "unexpected_ready_input"); + break; + } +#endif +} + +static void +chkio_drv_ready_event(ErlDrvData drv_data, + ErlDrvEvent event, + ErlDrvEventData event_data) +{ +#ifdef UNIX + ChkioDrvData *cddp = (ChkioDrvData *) drv_data; + switch (cddp->test) { + case CHKIO_DRIVER_EVENT: { +#ifdef HAVE_POLL_H + ChkioDriverEvent *cdep = cddp->test_data; + int fd = (int) event; + if (fd == cdep->in_fd) { + if (event_data->events == POLLIN + && event_data->revents == POLLIN) { + cdep->in_ok++; + } + else { + driver_failure_atom(cddp->port, "invalid_input_fd_events"); + } + break; + } + if (fd == cdep->out_fd) { + if (event_data->events == POLLOUT + && event_data->revents == POLLOUT) { + cdep->out_ok++; + } + else { + driver_failure_atom(cddp->port, "invalid_output_fd_events"); + } + break; + } +#endif + } + case CHKIO_STEAL: +#ifdef HAVE_POLL_H + break; +#endif + case CHKIO_STEAL_AUX: +#ifdef HAVE_POLL_H + break; +#endif + default: + driver_failure_atom(cddp->port, "unexpected_ready_event"); + break; + } +#endif /* UNIX */ +} + +static void +chkio_drv_timeout(ErlDrvData drv_data) +{ +#ifdef UNIX + ChkioDrvData *cddp = (ChkioDrvData *) drv_data; + switch (cddp->test) { + case CHKIO_FD_CHANGE: { + ChkioFdChange *cfcp = cddp->test_data; + int in_fd = cfcp->fds[0]; + int out_fd = cfcp->fds[1]; + if (in_fd >= 0) { + if (driver_select(cddp->port, (ErlDrvEvent) in_fd, DO_READ, 0) < 0) + driver_failure_atom(cddp->port, "deselect_failed"); + (void) write(out_fd, (void *) "!", 1); + close(out_fd); + close(in_fd); + } + if (pipe(cfcp->fds) < 0) { + driver_failure_posix(cddp->port, errno); + } + else { + if (driver_select(cddp->port, (ErlDrvEvent) cfcp->fds[0], + DO_READ, 1) < 0) + driver_failure_atom(cddp->port, "select_failed"); + if (cfcp->fds[0] == in_fd) + cfcp->same_fd++; + if (driver_set_timer(cddp->port, 10) < 0) + driver_failure_atom(cddp->port, "set_timer_failed"); + } + break; + } + case CHKIO_DRV_USE: + chkio_drv_use(cddp, chkio_drv_timeout); + break; + default: + driver_failure_atom(cddp->port, "unexpected_driver_timeout"); + break; + } +#endif /* UNIX */ +} + +static int +chkio_drv_control(ErlDrvData drv_data, + unsigned int command, + char *buf, int len, + char **rbuf, int rlen) +{ + char *res_str; + int res_len = -1; +#ifndef UNIX +#ifdef __WIN32__ + res_str = "skip: windows_different"; +#else + res_str = "nyiftos"; +#endif +#else + ChkioDrvData *cddp = (ChkioDrvData *) drv_data; + res_len = 0; + switch (command) { + case CHKIO_STOP: { + + /* + * --- STOP BEGIN --------------------------------------------------- + */ + switch (cddp->test) { + case CHKIO_STOP: + driver_failure_atom(cddp->port, "stop_when_stopped"); + break; + case CHKIO_USE_FALLBACK_POLLSET: { + char *c; + int i; + ChkioFallbackData *cbdp = (ChkioFallbackData *) cddp->test_data; + c = driver_alloc(sizeof(char)*(4*20+21*CHKIO_FALLBACK_FDS*8)); + if (!c) + return 0; + *rbuf = c; + c += sprintf(c, "/dev/null: "); + for (i = 0; i < CHKIO_FALLBACK_FDS; i++) { + c += sprintf(c, "%d=%d ", + cbdp->dev_null[i].fd, + cbdp->dev_null[i].cnt); + } + c += sprintf(c, "\n/dev/zero: "); + for (i = 0; i < CHKIO_FALLBACK_FDS; i++) { + c += sprintf(c, "%d=%d ", + cbdp->dev_zero[i].fd, + cbdp->dev_zero[i].cnt); + } + c += sprintf(c, "\npipe_in: "); + for (i = 0; i < CHKIO_FALLBACK_FDS; i++) { + c += sprintf(c, "%d=%d ", + cbdp->pipe_in[i].fd, + cbdp->pipe_in[i].cnt); + } + c += sprintf(c, "\npipe_out: "); + for (i = 0; i < CHKIO_FALLBACK_FDS; i++) { + c += sprintf(c, "%d=%d ", + cbdp->pipe_out[i].fd, + cbdp->pipe_out[i].cnt); + } + c += sprintf(c, "\n"); + res_len = (int) (c - *rbuf); + stop_use_fallback_pollset(cddp); + break; + } + case CHKIO_BAD_FD_IN_POLLSET: + res_str = "ok"; + res_len = -1; + stop_bad_fd_in_pollset(cddp); + break; + case CHKIO_DRIVER_EVENT: { + ChkioDriverEvent *cdep = cddp->test_data; + if (!cdep->in_ok || !cdep->out_ok) { + if (!cdep->in_ok) + driver_failure_atom(cddp->port, "got_no_input_events"); + if (!cdep->out_ok) + driver_failure_atom(cddp->port, "got_no_output_events"); + } + else { + char *c = driver_alloc(sizeof(char)*2*30); + if (!c) + driver_failure_posix(cddp->port, ENOMEM); + *rbuf = c; + res_len = sprintf(c, "in=%d\nout=%d\n", + cdep->in_ok, cdep->out_ok); + } + stop_driver_event(cddp); + break; + } + case CHKIO_FD_CHANGE: { + ChkioFdChange *cfcp = cddp->test_data; + if (!cfcp->same_fd) + driver_failure_atom(cddp->port, "never_same_fd"); + else { + char *c = driver_alloc(sizeof(char)*30); + if (!c) + driver_failure_posix(cddp->port, ENOMEM); + else { + *rbuf = c; + res_len = sprintf(c, "same_fd=%d\n", cfcp->same_fd); + } + } + stop_fd_change(cddp); + break; + } + case CHKIO_STEAL: + stop_steal(cddp); + res_str = "ok"; + res_len = -1; + break; + case CHKIO_STEAL_AUX: + stop_steal_aux(cddp); + res_str = "ok"; + res_len = -1; + break; + default: + driver_failure_atom(cddp->port, "invalid_state"); + break; + } + break; + } + /* + * --- STOP END ----------------------------------------------------- + */ + + case CHKIO_USE_FALLBACK_POLLSET: { + ChkioFallbackData *cbdp = driver_alloc(sizeof(ChkioFallbackData)); + cddp->test_data = (void *) cbdp; + if (!cbdp) + driver_failure_posix(cddp->port, ENOMEM); + else { + int i; + for (i = 0; i < CHKIO_FALLBACK_FDS; i++) { + cbdp->dev_null[i].fd = -1; + cbdp->dev_null[i].cnt = 0; + cbdp->dev_zero[i].fd = -1; + cbdp->dev_zero[i].cnt = 0; + cbdp->pipe_in[i].fd = -1; + cbdp->pipe_in[i].cnt = 0; + cbdp->pipe_out[i].fd = -1; + cbdp->pipe_out[i].cnt = 0; + } + for (i = 0; i < CHKIO_FALLBACK_FDS; i++) { + int fds[2]; + cbdp->dev_null[i].fd = open("/dev/null", O_WRONLY); + if (driver_select(cddp->port, + (ErlDrvEvent) cbdp->dev_null[i].fd, + DO_WRITE, + 1) != 0) { + driver_failure_posix(cddp->port, errno); + break; + } + cbdp->dev_zero[i].fd = open("/dev/zero", O_RDONLY); + if (driver_select(cddp->port, + (ErlDrvEvent) cbdp->dev_zero[i].fd, + DO_READ, + 1) != 0) { + driver_failure_posix(cddp->port, errno); + break; + } + if (pipe(fds) < 0) + driver_failure_posix(cddp->port, errno); + cbdp->pipe_in[i].fd = fds[0]; + cbdp->pipe_out[i].fd = fds[1]; + if (driver_select(cddp->port, + (ErlDrvEvent) cbdp->pipe_in[i].fd, + DO_READ, + 1) != 0) { + driver_failure_posix(cddp->port, EIO); + break; + } + if (i % 2 == 0) + (void) write(cbdp->pipe_out[i].fd, "!", 1); + if (driver_select(cddp->port, + (ErlDrvEvent) cbdp->pipe_out[i].fd, + DO_WRITE, + 1) != 0) { + driver_failure_posix(cddp->port, EIO); + break; + } + } + res_str = "ok"; + res_len = -1; + } + break; + } + case CHKIO_BAD_FD_IN_POLLSET: { + int i; + int error = 0; + int fds[11]; + for (i = 0; i < 11; i++) + fds[i] = -1; + /* We open a bunch of fds and use the last ones so we decrease the + risk of selecting on a fd that someone else just opened */ + for (i = 0; i < 10; i++) { + fds[i] = open("/dev/null", O_WRONLY); + if (fds[i] < 0) { + error = 1; + driver_failure_posix(cddp->port, errno); + break; + } + } + fds[10] = open("/dev/zero", O_RDONLY); + if (fds[10] < 0) { + error = 1; + driver_failure_posix(cddp->port, errno); + } + for (i = 0; i < 11; i++) { + if (fds[i] >= 0) + close(fds[i]); + } + if (!error) { + ChkioBadFdInPollset *bfipp; + bfipp = driver_alloc(sizeof(ChkioBadFdInPollset)); + if (!bfipp) + driver_failure_posix(cddp->port, ENOMEM); + else { + bfipp->fds[0] = fds[9]; + bfipp->fds[1] = fds[10]; + cddp->test_data = (void *) bfipp; + driver_select(cddp->port, (ErlDrvEvent) fds[9], DO_WRITE, 1); + driver_select(cddp->port, (ErlDrvEvent) fds[10], DO_READ, 1); + } + } + res_str = "ok"; + res_len = -1; + break; + } + case CHKIO_DRIVER_EVENT: { +#ifndef HAVE_POLL_H + res_str = "skip: Need the poll.h header for this test, but it doesn't exist"; + res_len = -1; +#else /* HAVE_POLL_H */ + int in_fd = open("/dev/zero", O_RDONLY); + int out_fd = open("/dev/null", O_WRONLY); + + if (in_fd < 0 || out_fd < 0) { + if (in_fd >= 0) + close(in_fd); + if (out_fd >= 0) + close(out_fd); + driver_failure_posix(cddp->port, errno); + } + else { + ChkioDriverEvent *cdep = driver_alloc(sizeof(ChkioDriverEvent)); + if (!cdep) + driver_failure_posix(cddp->port, ENOMEM); + else { + int res; + cddp->test_data = cdep; + + cdep->in_fd = in_fd; + cdep->in_data.events = POLLIN; + cdep->in_data.revents = 0; + cdep->in_ok = 0; + + res = driver_event(cddp->port, + (ErlDrvEvent) in_fd, + &cdep->in_data); + if (res < 0) { + res_str = "skip: driver_event() not supported"; + res_len = -1; + close(in_fd); + close(out_fd); + cdep->in_fd = -1; + cdep->out_fd = -1; + } + else { + res_str = "ok"; + res_len = -1; + + cdep->out_fd = out_fd; + cdep->out_data.events = POLLOUT; + cdep->out_data.revents = 0; + cdep->out_ok = 0; + + res = driver_event(cddp->port, + (ErlDrvEvent) out_fd, + &cdep->out_data); + if (res < 0) { + close(out_fd); + cdep->out_fd = -1; + driver_failure_atom(cddp->port, "driver_event_failed"); + } + } + + } + } +#endif /* HAVE_POLL_H */ + break; + } + case CHKIO_FD_CHANGE: { + ChkioFdChange *cfcp = driver_alloc(sizeof(ChkioFdChange)); + if (!cfcp) + driver_failure_posix(cddp->port, ENOMEM); + else { + cfcp->fds[0] = -1; + cfcp->fds[1] = -1; + cfcp->same_fd = 0; + cddp->test_data = cfcp; + driver_set_timer(cddp->port, 1); + res_str = "ok"; + res_len = -1; + } + break; + } + case CHKIO_STEAL: { + ChkioSteal *csp = driver_alloc(sizeof(ChkioSteal)); + char *c = driver_alloc(sizeof(char)*len+1); + if (!c || !csp) { + if (c) + driver_free(c); + if (csp) + driver_free(csp); + driver_failure_posix(cddp->port, ENOMEM); + res_str = "error"; + res_len = -1; + } + else { + int driver_event_fds[2]; + int driver_select_fds[2]; + cddp->test_data = csp; + memcpy(c, buf, len); + c[len] = '\0'; + if (sscanf(c, + "fds:%d:%d:%d:%d", + &driver_select_fds[0], + &driver_select_fds[1], + &driver_event_fds[0], + &driver_event_fds[1]) != 4) + driver_failure_atom(cddp->port, "bad_input"); + else { + int res = 0; + if (driver_event_fds[0] < 0) { /* Have no working driver_event() ... */ + csp->driver_select_fds[0] = driver_select_fds[0]; /* In */ + csp->driver_select_fds[1] = driver_select_fds[1]; /* Out */ + csp->driver_event_fds[0] = -1; + csp->driver_event_fds[1] = -1; + } + else { /* Have working driver_event() ... */ +#ifndef HAVE_POLL_H + driver_failure_atom(cddp->port, "unexpected_result"); + res = -1; +#else + csp->driver_select_fds[0] = driver_select_fds[0]; /* In */ + csp->driver_event_fds[1] = driver_select_fds[1]; /* Out */ + csp->driver_event_fds[0] = driver_event_fds[0]; /* In */ + csp->driver_select_fds[1] = driver_event_fds[1]; /* Out */ + + /* Steal with driver_event() */ + + csp->event_data[0].events = POLLIN; + csp->event_data[0].revents = 0; + res = driver_event(cddp->port, + (ErlDrvEvent) csp->driver_event_fds[0], + &csp->event_data[0]); + if (res < 0) + driver_failure_atom(cddp->port, + "driver_event_failed_to_steal"); + if (res >= 0) { + csp->event_data[1].events = POLLOUT; + csp->event_data[1].revents = 0; + res = driver_event(cddp->port, + (ErlDrvEvent) csp->driver_event_fds[1], + &csp->event_data[1]); + if (res < 0) + driver_failure_atom(cddp->port, + "driver_event_failed_to_steal"); + } +#endif + } + + /* Steal with driver_select() */ + if (res >= 0) { + res = driver_select(cddp->port, + (ErlDrvEvent) csp->driver_select_fds[0], + DO_READ, + 1); + if (res < 0) + driver_failure_atom(cddp->port, + "driver_select_failed_to_steal"); + } + if (res >= 0) { + res = driver_select(cddp->port, + (ErlDrvEvent) csp->driver_select_fds[1], + DO_WRITE, + 1); + if (res < 0) + driver_failure_atom(cddp->port, + "driver_select_failed_to_steal"); + } + + res_str = res >= 0 ? "ok" : "error"; + res_len = -1; + } + driver_free(c); + } + break; + } + case CHKIO_STEAL_AUX: { + int read_fds[2]; + int write_fds[2]; + + read_fds[0] = open("/dev/zero", O_RDONLY); + write_fds[0] = open("/dev/null", O_WRONLY); + +#ifdef HAVE_POLL_H + read_fds[1] = open("/dev/zero", O_RDONLY); + write_fds[1] = open("/dev/null", O_WRONLY); +#else + read_fds[1] = -1; + write_fds[1] = -1; +#endif + + if (read_fds[0] < 0 + || write_fds[0] < 0 +#ifdef HAVE_POLL_H + || read_fds[1] < 0 + || write_fds[1] < 0 +#endif + ) { + if (read_fds[0] < 0) + close(read_fds[0]); + if (write_fds[0] < 0) + close(write_fds[0]); +#ifdef HAVE_POLL_H + if (read_fds[1] < 0) + close(read_fds[1]); + if (write_fds[1] < 0) + close(write_fds[1]); +#endif + driver_failure_posix(cddp->port, errno); + } + else { + ChkioStealAux *csap = driver_alloc(sizeof(ChkioStealAux)); + if (!csap) { + driver_failure_posix(cddp->port, ENOMEM); + res_str = "error"; + res_len = -1; + } + else { + int res; + cddp->test_data = csap; + + csap->driver_select_fds[0] = read_fds[0]; + csap->driver_select_fds[1] = write_fds[0]; + + csap->driver_event_fds[0] = read_fds[1]; + csap->driver_event_fds[1] = write_fds[1]; + + res = driver_select(cddp->port, + (ErlDrvEvent) csap->driver_select_fds[0], + DO_READ, + 1); + if (res < 0) + driver_failure_atom(cddp->port, "driver_select_failed"); + if (res >= 0) { + res = driver_select(cddp->port, + (ErlDrvEvent) csap->driver_select_fds[1], + DO_WRITE, + 1); + if (res < 0) + driver_failure_atom(cddp->port, "driver_select_failed"); + } +#ifdef HAVE_POLL_H + if (res >= 0) { + csap->event_data[0].events = POLLIN; + csap->event_data[0].revents = 0; + res = driver_event(cddp->port, + (ErlDrvEvent) csap->driver_event_fds[0], + &csap->event_data[0]); + if (res < 0) { + close(csap->driver_event_fds[0]); + csap->driver_event_fds[0] = -1; + close(csap->driver_event_fds[1]); + csap->driver_event_fds[1] = -1; + res = 0; + } + else { + csap->event_data[1].events = POLLOUT; + csap->event_data[1].revents = 0; + res = driver_event(cddp->port, + (ErlDrvEvent) csap->driver_event_fds[1], + &csap->event_data[1]); + if (res < 0) + driver_failure_atom(cddp->port, + "driver_event_failed"); + } + } +#endif + if (res < 0) { + res_str = "error"; + res_len = -1; + } + else { + char *c = driver_alloc(sizeof(char)*(3+4*21+1)); + if (!c) { + res_str = "error"; + res_len = -1; + driver_failure_posix(cddp->port, ENOMEM); + } + else { + *rbuf = c; + res_len = sprintf(c, + "fds:%d:%d:%d:%d", + csap->driver_select_fds[0], + csap->driver_select_fds[1], + csap->driver_event_fds[0], + csap->driver_event_fds[1]); + } + } + } + } + break; + } + case CHKIO_SMP_SELECT: { + int rounds = 1; /*rand(); */ + ChkioSmpSelect* pip = (ChkioSmpSelect*) cddp->test_data; + if (pip == NULL) { + erl_drv_mutex_lock(smp_pipes_mtx); + if (smp_pipes) { + pip = smp_pipes; + smp_pipes = smp_pipes->next; + } + else { + cddp->test_data = driver_alloc(sizeof(ChkioSmpSelect)); + pip = (ChkioSmpSelect*) cddp->test_data; + pip->state = Closed; + pip->rand_state = 1; + smp_pipes_cnt++; + } + erl_drv_mutex_unlock(smp_pipes_mtx); + } + while (rounds--) { + int op = rand_r(&pip->rand_state); + switch (pip->state) { + case Closed: { + int fds[2], flags; + if (pipe(fds) < 0 || + (flags = fcntl(fds[0], F_GETFL, 0)) < 0 || + fcntl(fds[0], F_SETFL, flags|O_NONBLOCK) < 0) { + + driver_failure_posix(cddp->port, errno); + rounds = 0; + break; + } + TRACEF(("%T: Created pipe [%d->%d]\n", cddp->id, fds[1], fds[0])); + pip->read_fd = fds[0]; + pip->write_fd = fds[1]; + pip->state = Opened; + pip->wasSelected = 0; + pip->next_write = pip->next_read = rand_r(&pip->rand_state) % 1024; + if (op & 1) break; + op >>= 1; + }/*fall through*/ + case Opened: { + if (op & 1) { + TRACEF(("%T: Write %d to opened pipe [%d->%d]\n", cddp->id, pip->next_write, pip->write_fd, pip->read_fd)); + if (write(pip->write_fd, &pip->next_write, sizeof(int)) != sizeof(int)) { + fprintf(stderr, "Failed to write to pipe fd=%d, errno=%d\n", pip->write_fd, errno); + abort(); + } + pip->next_write++; + } + op >>= 1; + if (pip->wasSelected && (op & 1)) { + TRACEF(("%T: Close pipe [%d->%d]\n", cddp->id, pip->write_fd, pip->read_fd)); + if (close(pip->read_fd) || close(pip->write_fd)) { + fprintf(stderr, "Failed to close pipe, errno=%d\n", errno); + abort(); + } + pip->state = Closed; + break; + } + else { + TRACEF(("%T: Select on pipe [%d->%d]\n", cddp->id, pip->write_fd, pip->read_fd)); + if (driver_select(cddp->port, (ErlDrvEvent)pip->read_fd, DO_READ, 1)) { + fprintf(stderr, "driver_select failed for fd=%d\n", pip->read_fd); + abort(); + } + pip->state = Selected; + pip->wasSelected = 1; + op >>= 1; + if (pip->next_write != pip->next_read) { /* pipe not empty */ + if (op & 1) { + pip->state = Waiting; /* Wait for reader */ + break; + } + op >>= 1; + } + } + }/*fall through*/ + case Selected: + if (op & 1) { + TRACEF(("%T: Write %d to selected pipe [%d->%d]\n", cddp->id, + pip->next_write, pip->write_fd, pip->read_fd)); + if (write(pip->write_fd, &pip->next_write, sizeof(int)) != sizeof(int)) { + fprintf(stderr, "Failed to write to pipe fd=%d, errno=%d\n", pip->write_fd, errno); + abort(); + } + pip->next_write++; + } + op >>= 1; + if (op & 1) { + TRACEF(("%T: Deselect on pipe [%d->%d]\n", cddp->id, pip->write_fd, pip->read_fd)); + if (driver_select(cddp->port, (ErlDrvEvent)pip->read_fd, DO_READ, 0)) { + fprintf(stderr, "driver_(de)select failed for fd=%d\n", pip->read_fd); + abort(); + } + pip->state = Opened; + } + op >>= 1; + if (op & 1) { + TRACEF(("%T: Write %d to pipe [%d->%d] state=%d\n", cddp->id, + pip->next_write, pip->write_fd, pip->read_fd, pip->state)); + if (write(pip->write_fd, &pip->next_write, sizeof(int)) != sizeof(int)) { + fprintf(stderr, "Failed to write to pipe fd=%d, errno=%d\n", pip->write_fd, errno); + abort(); + } + pip->next_write++; + } + break; + case Waiting: + break; + default: + fprintf(stderr, "Strange state %d\n", pip->state); + abort(); + } + if (pip->state == Opened) { /* share unselected pipes with others */ + erl_drv_mutex_lock(smp_pipes_mtx); + pip->next = smp_pipes; + smp_pipes = pip; + erl_drv_mutex_unlock(smp_pipes_mtx); + cddp->test_data = NULL; + } + else { + cddp->test_data = pip; + } + } + res_str = "ok"; + res_len = -1; + break; + } + case CHKIO_DRV_USE: + chkio_drv_use(cddp, chkio_drv_control); + res_str = "ok"; + res_len = -1; + break; + default: + driver_failure_atom(cddp->port, "invalid_state"); + break; + } + cddp->test = command; +#endif /* UNIX */ + + if (res_len >= 0) + return res_len; + + res_len = strlen(res_str); + if (res_len > rlen) { + char *abuf = driver_alloc(sizeof(char)*res_len); + if (!abuf) + return 0; + *rbuf = abuf; + } + + memcpy((void *) *rbuf, (void *) res_str, res_len); + + return res_len; +} + +#ifdef UNIX + +#define ASSERT(cond) \ + do{ \ + if (!(cond)) { assert_failed(cddp->port, #cond, __LINE__); return; } \ + /*else fprintf(stderr, "Assertion '%s' at line %d: OK\r\n", #cond, __LINE__);*/ \ + }while(0) + +static void assert_print(char* str, int line) +{ + fprintf(stderr, "Assertion '%s' at line %d: FAILED\r\n", str, line); +} + +static void assert_failed(ErlDrvPort port, char* str, int line) +{ + char buf[30]; + assert_print(str,line); + snprintf(buf,sizeof(buf),"failed_at_line_%d",line); + driver_failure_atom(port,buf); + /*abort();*/ +} + +#define my_driver_select(PORT,FD,MODE,ON) \ + do{ if(driver_select(PORT, (ErlDrvEvent)(long)FD, MODE, ON) != 0) { \ + assert_failed(cddp->port, "driver_select", __LINE__); \ + return; \ + } \ + }while(0) + + +static void chkio_drv_use(ChkioDrvData *cddp, void* callback) +{ + ChkioDrvUse* cdu = (ChkioDrvUse*) cddp->test_data; + int fd_stop_select = -1; + + /*fprintf(stderr, "Callback: %p\r\n", callback);*/ + + if (cdu == NULL) { + int ret; + ASSERT(callback == chkio_drv_control); + cdu = &drv_use_singleton; + ASSERT(cdu->script_line == 0); + cddp->test_data = cdu; + cdu->fd_stop_select = -1; + cdu->script_line = 1; + cdu->fd_in = open("/dev/zero", O_RDONLY); + ASSERT(cdu->fd_in > 0); + cdu->fd_out = open("/dev/null", O_WRONLY); + ASSERT(cdu->fd_out > 0); + ret = pipe(cdu->fd_pipe); + ASSERT(ret == 0); + } + else { + if (callback == chkio_drv_timeout) { + if (cdu->fd_stop_select >= 0) { + fd_stop_select = cdu->fd_stop_select; + cdu->fd_stop_select = -1; + fprintf(stderr,"timeout detected stop_select fd=%d\r\n", fd_stop_select); + callback = chkio_drv_stop_select; + ASSERT(fd_stop_select == cdu->expected_fd); + } + else if (--cdu->timeouts_left > 0) { + driver_set_timer(cddp->port, 100); + return; + } + } + ASSERT(callback == cdu->expected_callback); + } + +#define NEXT_CALLBACK(fn) \ + cdu->expected_callback = fn; \ + /*fprintf(stderr, "Next expected callback: %p\r\n", fn);*/ \ + cdu->script_line = __LINE__; break; case __LINE__: \ + fprintf(stderr, "Script line %d\r\n", cdu->script_line) + + switch (cdu->script_line) { + case 1: + my_driver_select(cddp->port, cdu->fd_in, ERL_DRV_READ|ERL_DRV_USE, 1); + NEXT_CALLBACK(chkio_drv_ready_input); + + my_driver_select(cddp->port, cdu->fd_in, ERL_DRV_READ|ERL_DRV_USE, 0); + cdu->expected_fd = cdu->fd_in; + NEXT_CALLBACK(chkio_drv_stop_select); + + my_driver_select(cddp->port, cdu->fd_out, ERL_DRV_WRITE|ERL_DRV_USE, 1); + NEXT_CALLBACK(chkio_drv_ready_output); + + my_driver_select(cddp->port, cdu->fd_out, ERL_DRV_WRITE|ERL_DRV_USE, 0); + cdu->expected_fd = cdu->fd_out; + NEXT_CALLBACK(chkio_drv_stop_select); + + my_driver_select(cddp->port, cdu->fd_in, ERL_DRV_READ|ERL_DRV_USE, 1); + NEXT_CALLBACK(chkio_drv_ready_input); + + my_driver_select(cddp->port, cdu->fd_in, ERL_DRV_READ, 0); + NEXT_CALLBACK(chkio_drv_timeout); + + my_driver_select(cddp->port, cdu->fd_out, ERL_DRV_WRITE|ERL_DRV_USE, 1); + NEXT_CALLBACK(chkio_drv_ready_output); + + my_driver_select(cddp->port, cdu->fd_out, ERL_DRV_WRITE, 0); + NEXT_CALLBACK(chkio_drv_timeout); + + my_driver_select(cddp->port, cdu->fd_in, ERL_DRV_USE, 0); + cdu->expected_fd = cdu->fd_in; + NEXT_CALLBACK(chkio_drv_stop_select); + + my_driver_select(cddp->port, cdu->fd_out, ERL_DRV_USE, 0); + cdu->expected_fd = cdu->fd_out; + NEXT_CALLBACK(chkio_drv_stop_select); + + my_driver_select(cddp->port, cdu->fd_in, ERL_DRV_READ, 1); + NEXT_CALLBACK(chkio_drv_ready_input); + + my_driver_select(cddp->port, cdu->fd_in, ERL_DRV_USE, 0); + cdu->expected_fd = cdu->fd_in; + NEXT_CALLBACK(chkio_drv_stop_select); + + my_driver_select(cddp->port, cdu->fd_out, ERL_DRV_WRITE, 1); + NEXT_CALLBACK(chkio_drv_ready_output); + + my_driver_select(cddp->port, cdu->fd_out, ERL_DRV_USE, 0); + cdu->expected_fd = cdu->fd_out; + NEXT_CALLBACK(chkio_drv_stop_select); + + my_driver_select(cddp->port, cdu->fd_pipe[0], ERL_DRV_READ|ERL_DRV_USE, 1); + NEXT_CALLBACK(chkio_drv_timeout); + + my_driver_select(cddp->port, cdu->fd_pipe[0], ERL_DRV_USE, 0); + my_driver_select(cddp->port, cdu->fd_pipe[0], ERL_DRV_READ|ERL_DRV_USE, 1); + /* stop_select may or may not have been called up until now. + In either case it should not be called from here on. */ + cdu->fd_stop_select = -1; + NEXT_CALLBACK(chkio_drv_timeout); + + my_driver_select(cddp->port, cdu->fd_pipe[0], ERL_DRV_USE, 0); + cdu->expected_fd = cdu->fd_pipe[0]; + NEXT_CALLBACK(chkio_drv_stop_select); + + /* switch off USE again */ + my_driver_select(cddp->port, cdu->fd_pipe[0], ERL_DRV_USE, 0); + cdu->expected_fd = cdu->fd_pipe[0]; + NEXT_CALLBACK(chkio_drv_stop_select); + + my_driver_select(cddp->port, cdu->fd_pipe[1], ERL_DRV_READ|ERL_DRV_WRITE|ERL_DRV_USE, 1); + NEXT_CALLBACK(chkio_drv_ready_output); + + /* ERL_DRV_USE_NO_CALLBACK does not clear all */ + my_driver_select(cddp->port, cdu->fd_pipe[1], ERL_DRV_READ|ERL_DRV_USE_NO_CALLBACK, 0); + NEXT_CALLBACK(chkio_drv_ready_output); + + my_driver_select(cddp->port, cdu->fd_pipe[1], ERL_DRV_WRITE|ERL_DRV_USE_NO_CALLBACK, 0); + NEXT_CALLBACK(chkio_drv_timeout); + + cdu->script_line = 0; /* The End */ + cdu->expected_callback = chkio_drv_stop; + break; + + case 0: /* close port */ + ASSERT(cdu->fd_stop_select < 0); + close(cdu->fd_in); cdu->fd_in = -1; + close(cdu->fd_out); cdu->fd_out = -1; + close(cdu->fd_pipe[0]); cdu->fd_pipe[0] = -1; + close(cdu->fd_pipe[1]); cdu->fd_pipe[1] = -1; + /*driver_free(cdu); No, it's static */ + return; + + default: + ASSERT(0); + } + if (cdu->script_line) { + driver_set_timer(cddp->port, 100); + cdu->timeouts_left = 5; + } + else { + if (callback != chkio_drv_timeout) { + driver_cancel_timer(cddp->port); + } + driver_output(cddp->port, "TheEnd", 6); + } +} + +#endif /* UNIX */ + +static void chkio_drv_stop_select(ErlDrvEvent e, void* null) +{ +#ifdef UNIX + /*fprintf(stderr,"STOP_SELECT\r\n");*/ + if (!(null == NULL)) { + assert_print("null==NULL", __LINE__); abort(); + } + if (!(drv_use_singleton.fd_stop_select < 0)) { + assert_print("fd_stop_select<0", __LINE__); abort(); + } + drv_use_singleton.fd_stop_select = (int)(long)e; + /* Can't call chkio_drv_use directly here. That could even be recursive. + * Next timeout will detect it instead. + */ +#endif /* UNIX */ +} + + diff --git a/erts/emulator/test/driver_SUITE_data/invalid_extended_marker_drv.c b/erts/emulator/test/driver_SUITE_data/invalid_extended_marker_drv.c new file mode 100644 index 0000000000..59145447f8 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/invalid_extended_marker_drv.c @@ -0,0 +1,32 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +/* + * Author: Rickard Green + * + * Description: Implementation of a driver with an invalid extended + * marker. + */ + +#define VSN_MISMATCH_DRV_EXTENDED_MARKER (0xdeadbeef) +#define VSN_MISMATCH_DRV_NAME_STR "invalid_extended_marker_drv" +#define VSN_MISMATCH_DRV_NAME invalid_extended_marker_drv +#define VSN_MISMATCH_DRV_MAJOR_VSN_DIFF 0 +#define VSN_MISMATCH_DRV_MINOR_VSN_DIFF 0 + +#include "vsn_mismatch_drv_impl.c" diff --git a/erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c b/erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c new file mode 100644 index 0000000000..25d4b17001 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c @@ -0,0 +1,151 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#ifndef UNIX +#if !defined(__WIN32__) && !defined(_OSE_) && !defined(VXWORKS) +#define UNIX 1 +#endif +#endif + +#include <stdio.h> +#include <string.h> +#ifdef UNIX +#include <unistd.h> +#endif +#include "erl_driver.h" + +typedef struct { + ErlDrvPort port; + int fds[2]; +} IOReadyExitDrvData; + +static ErlDrvData io_ready_exit_drv_start(ErlDrvPort, char *); +static void io_ready_exit_drv_stop(ErlDrvData); +static void io_ready_exit_ready_input(ErlDrvData, ErlDrvEvent); +static void io_ready_exit_ready_output(ErlDrvData, ErlDrvEvent); +static void io_ready_exit_drv_output(ErlDrvData, char *, int); +static void io_ready_exit_drv_finish(void); +static int io_ready_exit_drv_control(ErlDrvData, unsigned int, + char *, int, char **, int); + +static ErlDrvEntry io_ready_exit_drv_entry = { + NULL, /* init */ + io_ready_exit_drv_start, + io_ready_exit_drv_stop, + NULL /* output */, + io_ready_exit_ready_input, + io_ready_exit_ready_output, + "io_ready_exit_drv", + NULL /* finish */, + NULL, /* handle */ + io_ready_exit_drv_control, + NULL, /* timeout */ + NULL, /* outputv */ + NULL /* ready_async */ +}; + +/* ------------------------------------------------------------------------- +** Entry functions +**/ + +DRIVER_INIT(io_ready_exit_drv) +{ + return &io_ready_exit_drv_entry; +} + +static ErlDrvData +io_ready_exit_drv_start(ErlDrvPort port, char *command) { + IOReadyExitDrvData *oeddp = driver_alloc(sizeof(IOReadyExitDrvData)); + oeddp->port = port; + oeddp->fds[0] = -1; + oeddp->fds[1] = -1; + return (ErlDrvData) oeddp; +} + +static void +io_ready_exit_drv_stop(ErlDrvData drv_data) { + IOReadyExitDrvData *oeddp = (IOReadyExitDrvData *) drv_data; +#ifdef UNIX + if (oeddp->fds[0] >= 0) { + driver_select(oeddp->port, + (ErlDrvEvent) oeddp->fds[0], + DO_READ|DO_WRITE, + 0); + close(oeddp->fds[0]); + } + if (oeddp->fds[1] >= 0) + close(oeddp->fds[1]); +#endif + driver_free((void *) oeddp); +} + + +static void +io_ready_exit_ready_output(ErlDrvData drv_data, ErlDrvEvent event) +{ + IOReadyExitDrvData *oeddp = (IOReadyExitDrvData *) drv_data; + driver_failure_atom(oeddp->port, "ready_output_driver_failure"); +} + +static void +io_ready_exit_ready_input(ErlDrvData drv_data, ErlDrvEvent event) +{ + IOReadyExitDrvData *oeddp = (IOReadyExitDrvData *) drv_data; + driver_failure_atom(oeddp->port, "ready_input_driver_failure"); +} + +static int +io_ready_exit_drv_control(ErlDrvData drv_data, + unsigned int command, + char *buf, int len, + char **rbuf, int rlen) +{ + char *abuf; + char *res_str; + int res_len; + IOReadyExitDrvData *oeddp = (IOReadyExitDrvData *) drv_data; +#ifndef UNIX + res_str = "nyiftos"; +#else + if (pipe(oeddp->fds) < 0) { + res_str = "pipe failed"; + } + else { + res_str = "ok"; + write(oeddp->fds[1], "!", 1); + driver_select(oeddp->port, + (ErlDrvEvent) oeddp->fds[0], + DO_READ|DO_WRITE, + 1); + } +#endif + res_len = strlen(res_str); + if (res_len > rlen) { + abuf = driver_alloc(sizeof(char)*res_len); + if (!abuf) + return 0; + *rbuf = abuf; + } + + memcpy((void *) *rbuf, (void *) res_str, res_len); + + return res_len; +} + + + diff --git a/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c b/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c new file mode 100644 index 0000000000..2048d06123 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c @@ -0,0 +1,423 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +/* + * Author: Rickard Green + * + * Description: Tests that port I/O queues can be flushed via: + * - ready_input(), + * - ready_output(), + * - timeout(), + * - driver_async() -> read_async(), and + * - event() + */ + +#ifndef UNIX +#if !defined(__WIN32__) && !defined(_OSE_) && !defined(VXWORKS) +#define UNIX 1 +#endif +#endif + +#if defined(DEBUG) || 0 +# define PRINTF(X) printf X +#else +# define PRINTF(X) +#endif + +#if defined(UNIX) +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#ifdef HAVE_POLL_H +# include <poll.h> +#endif +#elif defined(__WIN32__) +#include <windows.h> +#endif + +#include <errno.h> + +#include "erl_driver.h" + +typedef enum { + IOQ_EXIT_INVALID = 0, + IOQ_EXIT_READY_INPUT = 1, + IOQ_EXIT_READY_OUTPUT = 2, + IOQ_EXIT_TIMEOUT = 3, + IOQ_EXIT_READY_ASYNC = 4, + IOQ_EXIT_EVENT = 5, + IOQ_EXIT_READY_INPUT_ASYNC = 6, + IOQ_EXIT_READY_OUTPUT_ASYNC = 7, + IOQ_EXIT_TIMEOUT_ASYNC = 8, + IOQ_EXIT_EVENT_ASYNC = 9 +} IOQExitTest; + +typedef struct { + ErlDrvPort port; + IOQExitTest test; + int ifd; + int ofd; + int outstanding_async_task; + long async_task; +#ifdef HAVE_POLL_H + struct erl_drv_event_data event_data; +#endif +} IOQExitDrvData; + +#define EV2FD(EV) ((int) ((long) (EV))) +#define FD2EV(FD) ((ErlDrvEvent) ((long) (FD))) + +static ErlDrvData start(ErlDrvPort port, char *command); +static void stop(ErlDrvData drv_data); +static void ready_input(ErlDrvData drv_data, ErlDrvEvent event); +static void ready_output(ErlDrvData drv_data, ErlDrvEvent event); +static int control(ErlDrvData, unsigned int, char *, int, char **, int); +static void timeout(ErlDrvData drv_data); +static void ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data); +static void flush(ErlDrvData drv_data); +static void event(ErlDrvData drv_data, ErlDrvEvent event, + ErlDrvEventData event_data); +static void async_invoke(void*); +static void do_driver_async(IOQExitDrvData *); + +static ErlDrvEntry ioq_exit_drv_entry = { + NULL /* init */, + start, + stop, + NULL /* output */, + ready_input, + ready_output, + "ioq_exit_drv", + NULL /* finish */, + NULL /* handle */, + control, + timeout, + NULL /* outputv */, + ready_async, + flush, + NULL /* call */, + event, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + ERL_DRV_FLAG_USE_PORT_LOCKING, + NULL /* handle2 */, + NULL /* process_exit */ +}; + +DRIVER_INIT(ioq_exit_drv) +{ + return &ioq_exit_drv_entry; +} + +static ErlDrvData +start(ErlDrvPort port, char *command) +{ + IOQExitDrvData *ddp = driver_alloc(sizeof(IOQExitDrvData)); + PRINTF(("%p = start(%ld, %s) called\r\n", ddp, (long) port, command)); + if (!ddp) { + errno = ENOMEM; + return ERL_DRV_ERROR_ERRNO; + } + + ddp->port = port; + ddp->test = IOQ_EXIT_INVALID; + ddp->ifd = -1; + ddp->ofd = -1; + ddp->outstanding_async_task = 0; + ddp->async_task = -1; +#ifdef HAVE_POLL_H + ddp->event_data.events = (short) 0; + ddp->event_data.revents = (short) 0; +#endif + + return (ErlDrvData) ddp; +} + +static int control(ErlDrvData drv_data, + unsigned int command, + char *buf, int len, + char **rbuf, int rlen) +{ + IOQExitDrvData *ddp = (IOQExitDrvData *) drv_data; + char *res_str = "nyiftos"; + + PRINTF(("control(%p, %d, ...) called\r\n", drv_data, command)); + + switch (command) { + case IOQ_EXIT_READY_INPUT: + case IOQ_EXIT_READY_INPUT_ASYNC: +#ifdef UNIX + ddp->ifd = open("/dev/zero", O_RDONLY); + if (ddp->ifd < 0) { + driver_failure_posix(ddp->port, errno); + return 0; + } + break; +#else + goto done; +#endif + case IOQ_EXIT_READY_OUTPUT: + case IOQ_EXIT_READY_OUTPUT_ASYNC: +#ifdef UNIX + ddp->ofd = open("/dev/null", O_WRONLY); + if (ddp->ofd < 0) { + driver_failure_posix(ddp->port, errno); + return 0; + } + break; +#else + goto done; +#endif + case IOQ_EXIT_EVENT: + case IOQ_EXIT_EVENT_ASYNC: +#ifdef UNIX +#ifdef HAVE_POLL_H + ddp->ofd = open("/dev/null", O_WRONLY); + if (ddp->ofd < 0) { + driver_failure_posix(ddp->port, errno); + return 0; + } + else if (driver_event(ddp->port, FD2EV(ddp->ofd), NULL) != 0) { + res_str = "skip: driver_event() not supported"; + goto done; + } +#else + res_str = "skip: No poll.h found which is needed for this test"; + goto done; +#endif + break; +#else /* UNIX */ + goto done; +#endif + case IOQ_EXIT_TIMEOUT: + case IOQ_EXIT_TIMEOUT_ASYNC: + break; + case IOQ_EXIT_READY_ASYNC: + break; + default: + res_str = "error: command not supported"; + goto done; + } + + driver_enq(ddp->port, "!", 1); + ddp->test = (IOQExitTest) command; + res_str = "ok"; + + done: { + int res_len = strlen(res_str); + if (res_len > rlen) { + char *abuf = driver_alloc(sizeof(char)*res_len); + if (!abuf) + return 0; + *rbuf = abuf; + } + + memcpy((void *) *rbuf, (void *) res_str, res_len); + + return res_len; + } +} + +static void stop(ErlDrvData drv_data) +{ + IOQExitDrvData *ddp = (IOQExitDrvData *) drv_data; + + PRINTF(("stop(%p) called\r\n", drv_data)); + + if (ddp) { + switch (ddp->test) { +#ifdef UNIX + case IOQ_EXIT_READY_INPUT: + case IOQ_EXIT_READY_INPUT_ASYNC: + if (ddp->ifd >= 0) { + driver_select(ddp->port, FD2EV(ddp->ifd), DO_READ, 0); + close(ddp->ifd); + } + break; + case IOQ_EXIT_READY_OUTPUT: + case IOQ_EXIT_READY_OUTPUT_ASYNC: + if (ddp->ofd >= 0) { + driver_select(ddp->port, FD2EV(ddp->ofd), DO_WRITE, 0); + close(ddp->ofd); + } + break; + case IOQ_EXIT_EVENT: + case IOQ_EXIT_EVENT_ASYNC: + if (ddp->ofd >= 0) { + driver_event(ddp->port, FD2EV(ddp->ofd), NULL); + close(ddp->ofd); + } + break; +#endif + case IOQ_EXIT_TIMEOUT: + case IOQ_EXIT_TIMEOUT_ASYNC: + driver_cancel_timer(ddp->port); + break; + case IOQ_EXIT_READY_ASYNC: + if (ddp->outstanding_async_task) + driver_async_cancel(ddp->async_task); + break; + default: + break; + } + driver_free(ddp); + } +} + + +static void flush(ErlDrvData drv_data) +{ + IOQExitDrvData *ddp = (IOQExitDrvData *) drv_data; + + PRINTF(("flush(%p) called\r\n", drv_data)); + + switch (ddp->test) { +#ifdef UNIX + case IOQ_EXIT_READY_INPUT: + case IOQ_EXIT_READY_INPUT_ASYNC: + driver_select(ddp->port, FD2EV(ddp->ifd), DO_READ, 1); + break; + case IOQ_EXIT_READY_OUTPUT: + case IOQ_EXIT_READY_OUTPUT_ASYNC: + driver_select(ddp->port, FD2EV(ddp->ofd), DO_WRITE, 1); + break; + case IOQ_EXIT_EVENT: + case IOQ_EXIT_EVENT_ASYNC: +#ifdef HAVE_POLL_H + ddp->event_data.events |= POLLOUT; + driver_event(ddp->port, FD2EV(ddp->ofd), &ddp->event_data); +#endif + break; +#endif + case IOQ_EXIT_TIMEOUT: + case IOQ_EXIT_TIMEOUT_ASYNC: + driver_set_timer(ddp->port, 0); + break; + case IOQ_EXIT_READY_ASYNC: + do_driver_async(ddp); + break; + default: + break; + } +} + +static void ready_input(ErlDrvData drv_data, ErlDrvEvent event) +{ + IOQExitDrvData *ddp = (IOQExitDrvData *) drv_data; + + PRINTF(("ready_input(%p, %d) called\r\n", drv_data, EV2FD(event))); + +#ifdef UNIX + if (ddp->ifd == EV2FD(event)) { + driver_select(ddp->port, FD2EV(ddp->ifd), DO_READ, 0); + close(ddp->ifd); + ddp->ifd = -1; + if (ddp->test == IOQ_EXIT_READY_INPUT_ASYNC) + do_driver_async(ddp); + else + driver_deq(ddp->port, 1); + } +#endif +} + +static void ready_output(ErlDrvData drv_data, ErlDrvEvent event) +{ + IOQExitDrvData *ddp = (IOQExitDrvData *) drv_data; + + PRINTF(("ready_output(%p, %d) called\r\n", drv_data, EV2FD(event))); + +#ifdef UNIX + if (ddp->ofd == EV2FD(event)) { + driver_select(ddp->port, FD2EV(ddp->ofd), DO_WRITE, 0); + close(ddp->ofd); + ddp->ofd = -1; + if (ddp->test == IOQ_EXIT_READY_OUTPUT_ASYNC) + do_driver_async(ddp); + else + driver_deq(ddp->port, 1); + } +#endif +} + +static void timeout(ErlDrvData drv_data) +{ + IOQExitDrvData *ddp = (IOQExitDrvData *) drv_data; + + PRINTF(("timeout(%p) called\r\n", drv_data)); + + if (ddp->test == IOQ_EXIT_TIMEOUT_ASYNC) + do_driver_async(ddp); + else + driver_deq(ddp->port, 1); +} + +static void ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data) +{ + IOQExitDrvData *ddp = (IOQExitDrvData *) drv_data; + + PRINTF(("ready_async(%p, %p) called\r\n", drv_data, thread_data)); + + if (drv_data == (ErlDrvData) thread_data) { + driver_deq(ddp->port, 1); + ddp->outstanding_async_task = 0; + } +} + +static void event(ErlDrvData drv_data, + ErlDrvEvent event, + ErlDrvEventData event_data) +{ + IOQExitDrvData *ddp = (IOQExitDrvData *) drv_data; + + PRINTF(("event(%p, %d, %p) called\r\n", drv_data, EV2FD(event), event_data)); + +#if defined(UNIX) && defined(HAVE_POLL_H) + if (ddp->ofd == EV2FD(event)) { + driver_event(ddp->port, FD2EV(ddp->ofd), NULL); + close(ddp->ofd); + ddp->ofd = -1; + if (ddp->test == IOQ_EXIT_EVENT_ASYNC) + do_driver_async(ddp); + else + driver_deq(ddp->port, 1); + } +#endif +} + +static void async_invoke(void *arg) +{ + PRINTF(("async_invoke(%p) called\r\n", arg)); +} + +static void do_driver_async(IOQExitDrvData *ddp) +{ + ErlDrvSysInfo si; + long task; + ddp->outstanding_async_task = 1; + task = driver_async(ddp->port, NULL, async_invoke, ddp, NULL); + /* If no async threads, ddp has been deallocated now */ + driver_system_info(&si, sizeof(ErlDrvSysInfo)); + if (si.async_threads) + ddp->async_task = task; +} + + diff --git a/erts/emulator/test/driver_SUITE_data/larger_major_vsn_drv.c b/erts/emulator/test/driver_SUITE_data/larger_major_vsn_drv.c new file mode 100644 index 0000000000..4eb0e6fa57 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/larger_major_vsn_drv.c @@ -0,0 +1,31 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +/* + * Author: Rickard Green + * + * Description: Implementation of a driver with a larger major + * driver version than the current system. + */ + +#define VSN_MISMATCH_DRV_NAME_STR "larger_major_vsn_drv" +#define VSN_MISMATCH_DRV_NAME larger_major_vsn_drv +#define VSN_MISMATCH_DRV_MAJOR_VSN_DIFF 1 +#define VSN_MISMATCH_DRV_MINOR_VSN_DIFF 0 + +#include "vsn_mismatch_drv_impl.c" diff --git a/erts/emulator/test/driver_SUITE_data/larger_minor_vsn_drv.c b/erts/emulator/test/driver_SUITE_data/larger_minor_vsn_drv.c new file mode 100644 index 0000000000..396deb9bef --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/larger_minor_vsn_drv.c @@ -0,0 +1,31 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +/* + * Author: Rickard Green + * + * Description: Implementation of a driver with a larger minor + * driver version than the current system. + */ + +#define VSN_MISMATCH_DRV_NAME_STR "larger_minor_vsn_drv" +#define VSN_MISMATCH_DRV_NAME larger_minor_vsn_drv +#define VSN_MISMATCH_DRV_MAJOR_VSN_DIFF 0 +#define VSN_MISMATCH_DRV_MINOR_VSN_DIFF 1 + +#include "vsn_mismatch_drv_impl.c" diff --git a/erts/emulator/test/driver_SUITE_data/many_events_drv.c b/erts/emulator/test/driver_SUITE_data/many_events_drv.c new file mode 100644 index 0000000000..7417dbf7f8 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/many_events_drv.c @@ -0,0 +1,98 @@ +#ifdef __WIN32__ +#include <windows.h> +#endif + +#include <stdio.h> +#include "erl_driver.h" + +static ErlDrvPort erlang_port; +static ErlDrvData many_events_start(ErlDrvPort, char *); +static void from_erlang(ErlDrvData, char*, int); +static void from_port(ErlDrvData drv_data, ErlDrvEvent event); +static int many_events_call(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen, unsigned *ret_flags); +static ErlDrvEntry many_events_driver_entry = { + NULL, /* Init */ + many_events_start, + NULL, /* Stop */ + from_erlang, + from_port, /* Ready input */ + NULL, /* Ready output */ + "many_events_drv", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + many_events_call +}; + +DRIVER_INIT(many_events_drv) +{ + return &many_events_driver_entry; +} + +static ErlDrvData +many_events_start(ErlDrvPort port, char *buf) +{ + return (ErlDrvData) port; +} + +static void +from_erlang(ErlDrvData data, char *buf, int count) +{ + int i; + int num; + char *b2 = driver_alloc(count + 1); + char b3[1024]; + + memcpy(b2,buf,count); + b2[count] = '\0'; + + num = atoi(b2); + + driver_free(b2); + + if(num < 0) + num = 0; +#ifdef __WIN32__ + for (i = 0; i < num; ++i) { + HANDLE ev = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (ev == INVALID_HANDLE_VALUE || + driver_select((ErlDrvPort) data, (ErlDrvEvent) ev, + DO_READ, 1) != 0) { + break; + } + SetEvent(ev); + } +#else + i = num; +#endif + sprintf(b3,"%d",i); + driver_output((ErlDrvPort) data, b3, strlen(b3)); +} + +static void from_port(ErlDrvData data, ErlDrvEvent ev) +{ +#ifdef __WIN32__ + /*static int counter = 0;*/ + driver_select((ErlDrvPort) data, (ErlDrvEvent) ev, + DO_READ, 0); + CloseHandle((HANDLE) ev); + /*fprintf(stderr,"Close no %d\r\n",counter++);*/ +#endif + return; +} + +static int +many_events_call(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen, unsigned *ret_flags) +{ + *rbuf = buf; + *ret_flags |= DRIVER_CALL_KEEP_BUFFER; + return len; +} + diff --git a/erts/emulator/test/driver_SUITE_data/missing_callback_drv.c b/erts/emulator/test/driver_SUITE_data/missing_callback_drv.c new file mode 100644 index 0000000000..c80e492e3f --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/missing_callback_drv.c @@ -0,0 +1,144 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson AB. Portions + * created by Ericsson are Copyright 2008, Ericsson Utvecklings AB. All + * Rights Reserved.'' + * + * $Id$ + */ + +#ifndef UNIX +#if !defined(__WIN32__) && !defined(_OSE_) && !defined(VXWORKS) +#define UNIX 1 +#endif +#endif + +#ifdef UNIX +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#ifdef HAVE_POLL_H +# include <poll.h> +#endif +#endif /* UNIX */ + +#include "erl_driver.h" + +typedef struct { + int ofd; + int ifd; + int efd; +#ifdef HAVE_POLL_H + struct erl_drv_event_data edata; +#endif +} mcd_data_t; + +static ErlDrvData start(ErlDrvPort port, char *command); +static void stop(ErlDrvData data); + +static ErlDrvEntry missing_callback_drv_entry = { + NULL /* init */, + start, + stop, + NULL /* output */, + NULL /* ready_input */, + NULL /* ready_output */, + "missing_callback_drv", + NULL /* finish */, + NULL /* handle */, + NULL /* control */, + NULL /* timeout */, + NULL /* outputv */, + NULL /* ready_async */, + NULL /* flush */, + NULL /* call */, + NULL /* event */, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + ERL_DRV_FLAG_USE_PORT_LOCKING, + NULL, /* handle2 */ + NULL /* process_exit */ +}; + +DRIVER_INIT(missing_callback_drv) +{ + return &missing_callback_drv_entry; +} + +static ErlDrvData +start(ErlDrvPort port, char *command) +{ + mcd_data_t *mcd = driver_alloc(sizeof(mcd_data_t)); + + if (!mcd) + goto error; + + mcd->ofd = -1; + mcd->ifd = -1; + mcd->efd = -1; + +#ifdef UNIX + + mcd->ofd = open("/dev/null", O_WRONLY); + if (mcd->ofd < 0) + goto error; + if (driver_select(port, (ErlDrvEvent) (long) mcd->ofd, DO_WRITE, 1) != 0) + goto error; + + mcd->ifd = open("/dev/zero", O_RDONLY); + if (mcd->ifd < 0) + goto error; + if (driver_select(port, (ErlDrvEvent) (long) mcd->ifd, DO_READ, 1) != 0) + goto error; + +#ifdef HAVE_POLL_H + mcd->efd = open("/dev/null", O_WRONLY); + if (mcd->efd < 0) + goto error; + mcd->edata.events = POLLOUT; + mcd->edata.revents = 0; + driver_event(port, (ErlDrvEvent) (long) mcd->efd, &mcd->edata); +#endif +#endif + + driver_set_timer(port, 0); + + return (ErlDrvData) mcd; + + error: + stop((ErlDrvData) mcd); + return ERL_DRV_ERROR_GENERAL; +} + +static void +stop(ErlDrvData data) +{ + mcd_data_t *mcd = (mcd_data_t *) data; + if (mcd) { +#ifdef UNIX + if (mcd->ofd >= 0) + close(mcd->ofd); + if (mcd->ifd >= 0) + close(mcd->ifd); +#ifdef HAVE_POLL_H + if (mcd->efd >= 0) + close(mcd->efd); +#endif +#endif + driver_free(mcd); + } +} diff --git a/erts/emulator/test/driver_SUITE_data/monitor_drv.c b/erts/emulator/test/driver_SUITE_data/monitor_drv.c new file mode 100644 index 0000000000..1da6a56a72 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/monitor_drv.c @@ -0,0 +1,293 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include <stdio.h> +#include <string.h> +#include "erl_driver.h" + +static ErlDrvData monitor_drv_start(ErlDrvPort, char *); +static int monitor_drv_control(ErlDrvData, unsigned int, + char *, int, char **, int); +static void handle_monitor(ErlDrvData drv_data, ErlDrvMonitor *monitor); + +#define OP_I_AM_IPID 1 +#define OP_MONITOR_ME 2 +#define OP_DEMONITOR_ME 3 +#define OP_MONITOR_ME_LATER 4 +#define OP_DO_DELAYED_MONITOR 5 + +typedef struct one_monitor { + ErlDrvTermData pid; + int later_id; + ErlDrvMonitor mon; + struct one_monitor *next; +} OneMonitor; + + +typedef struct { + ErlDrvPort port; + ErlDrvTermData ipid; + int later_counter; + OneMonitor *first; +} MyDrvData; + + +static ErlDrvEntry monitor_drv_entry = { + NULL /* init */, + monitor_drv_start, + NULL /* stop */, + NULL /* output */, + NULL /* ready_input */, + NULL /* ready_output */, + "monitor_drv", + NULL /* finish */, + NULL /* handle */, + monitor_drv_control, + NULL /* timeout */, + NULL /* outputv */, + NULL /* ready_async */, + NULL /* flush */, + NULL /* call */, + NULL /* event */, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, /* handle2 */ + handle_monitor +}; + +DRIVER_INIT(monitor_drv) +{ + return &monitor_drv_entry; +} + +static ErlDrvData +monitor_drv_start(ErlDrvPort port, char *command) { + MyDrvData *data = driver_alloc(sizeof(MyDrvData)); + data->port = port; + data->ipid = driver_term_nil; + data->first = NULL; + data->later_counter = 0; + return (ErlDrvData) data; +} + +static void monitor_drv_stop(ErlDrvData data) +{ + driver_free((void *) data); +} + +static void handle_monitor(ErlDrvData drv_data, ErlDrvMonitor *monitor) +{ + + MyDrvData *data = (MyDrvData *) drv_data; + OneMonitor *p,*o; + for (p = data->first, o = NULL; + p != NULL && driver_compare_monitors(&p->mon,monitor); + o = p, p = p->next) + ; + if (!p) { + fprintf(stderr,"Spooky Monitor executed!\r\n"); + } else { + ErlDrvTermData spec[] = { + ERL_DRV_ATOM, driver_mk_atom("monitor_fired"), + ERL_DRV_PORT, driver_mk_port(data->port), + ERL_DRV_PID, p->pid, + ERL_DRV_TUPLE, TERM_DATA(3) + }; + if (!o) { + data->first = p->next; + } else { + o->next = p->next; + } + driver_free(p); + driver_send_term(data->port, data->ipid, spec, sizeof(spec)/sizeof(ErlDrvTermData)); + } + + return; +} + +static int +monitor_drv_control(ErlDrvData drv_data, + unsigned int command, + char *ibuf, int ilen, + char **rbuf, int rlen) +{ + MyDrvData *data = (MyDrvData *) drv_data; + char *answer = NULL; + char buff[64]; + int alen; + + switch (command) { + case OP_I_AM_IPID: + data->ipid = driver_caller(data->port); + answer = "ok"; + break; + case OP_MONITOR_ME: + { + int res; + OneMonitor *om = driver_alloc(sizeof(OneMonitor)); + om->pid = driver_caller(data->port); + om->later_id = 0; + res = driver_monitor_process(data->port,om->pid,&(om->mon)); + if (res < 0) { + answer = "error"; + driver_free(om); + } else if (res > 0) { + answer = "noproc"; + driver_free(om); + } else { + om->next = data->first; + data->first = om; + answer = "ok"; + } + break; + } + case OP_DEMONITOR_ME: + { + int res; + OneMonitor *p,*q = NULL; + int found = 0; + ErlDrvTermData pid = driver_caller(data->port); + for (p = data->first; p != NULL; p = p->next) { + if (p->pid == pid) { + q = p; + ++found; + } + } + if (q == NULL) { + answer = "not_monitored"; + } else { + if (q->later_id > 0) { + if (found > 1) { + answer = "delayd_but_more"; + } else { + answer = "delayed"; + } + } else { + res = driver_demonitor_process(data->port, &(q->mon)); + if (res < 0) { + answer = "error"; + } else if (res > 0) { + if (found > 1) { + answer = "gone_but_more"; + } else { + answer = "gone"; + } + } else { + if (found > 1) { + answer = "ok_but_more"; + } else { + answer = "ok"; + } + } + } + if (data->first == q) { + data->first = q->next; + } else { + for (p = data->first; p != NULL; p = p->next) { + if (p->next == q) { + p->next = q->next; + break; + } + } + } + driver_free(q); + } + break; + } + case OP_MONITOR_ME_LATER: + { + int res; + OneMonitor *om = driver_alloc(sizeof(OneMonitor)); + om->pid = driver_caller(data->port); + om->later_id = (++(data->later_counter)); + om->next = data->first; + data->first = om; + sprintf(buff,"ok:%d",om->later_id); + answer = buff; + break; + } + case OP_DO_DELAYED_MONITOR: + { + int id = 0, sign = 1, in_number = 0; + OneMonitor *p, *q; + char *bp; + for (bp = ibuf; bp < (ibuf + ilen); ++bp) { + if (*bp <= '9' && *bp >= '0') { + int x = *bp - '0'; + in_number++; + id *= 10; + id += x; + } else if (*bp == '-') { + if (in_number) { + break; + } + sign = -1; + ++in_number; + } else { + if (in_number) { + break; + } + } + } + id *= sign; + q = NULL; + for (p = data->first; p != NULL; q = p, p = p->next) { + if (p->later_id != 0 && p->later_id == id) { + break; + } + } + if (p == NULL) { + answer = "not_found"; + } else { + int res = driver_monitor_process(data->port,p->pid,&(p->mon)); + if (res != 0) { + if (res < 0) { + answer = "error"; + } else { + answer = "noproc"; + } + if (q == NULL) { + data->first = p->next; + } else { + q->next = p->next; + } + driver_free(p); + } else { + p->later_id = 0; + answer = "ok"; + } + } + break; + } + default: + answer = "unknown_op"; + } + if (answer == NULL) { + answer = "internal_error"; + } + alen = strlen(answer); + if (alen >= rlen) { + *rbuf = driver_alloc(alen+1); + } + strcpy(*rbuf,answer); + return alen; +} + + diff --git a/erts/emulator/test/driver_SUITE_data/otp_6879_drv.c b/erts/emulator/test/driver_SUITE_data/otp_6879_drv.c new file mode 100644 index 0000000000..8c0a9aadfd --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/otp_6879_drv.c @@ -0,0 +1,71 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include <stdio.h> +#include <string.h> +#include "erl_driver.h" + +static int call(ErlDrvData drv_data, + unsigned int command, + char *buf, int len, + char **rbuf, int rlen, + unsigned int *flags); + +static ErlDrvEntry otp_6879_drv_entry = { + NULL /* init */, + NULL /* start */, + NULL /* stop */, + NULL /* output */, + NULL /* ready_input */, + NULL /* ready_output */, + "otp_6879_drv", + NULL /* finish */, + NULL /* handle */, + NULL /* control */, + NULL /* timeout */, + NULL /* outputv */, + NULL /* ready_async */, + NULL /* flush */, + call, + NULL /* event */, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + ERL_DRV_FLAG_USE_PORT_LOCKING, + NULL /* handle2 */, + NULL /* handle_monitor */ +}; + +DRIVER_INIT(otp_6879_drv) +{ + return &otp_6879_drv_entry; +} + + +static int call(ErlDrvData drv_data, + unsigned int command, + char *buf, int len, + char **rbuf, int rlen, + unsigned int *flags) +{ + /* echo call */ + if (len > rlen) + *rbuf = driver_alloc(len); + memcpy((void *) *rbuf, (void *) buf, len); + return len; +} diff --git a/erts/emulator/test/driver_SUITE_data/outputv_drv.c b/erts/emulator/test/driver_SUITE_data/outputv_drv.c new file mode 100644 index 0000000000..87f66ae413 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/outputv_drv.c @@ -0,0 +1,63 @@ +#include <stdio.h> +#include "erl_driver.h" + +static ErlDrvPort erlang_port; +static ErlDrvData outputv_start(ErlDrvPort, char*); +static void outputv_stop(ErlDrvData), outputv_read(ErlDrvData, char*, int), outputv(ErlDrvData, ErlIOVec*); + +static ErlDrvEntry outputv_driver_entry = +{ + NULL, + outputv_start, + outputv_stop, + outputv_read, + NULL, + NULL, + "outputv_drv", + NULL, + NULL, + NULL, + NULL, + outputv, + NULL +}; + +DRIVER_INIT(outputv_drv) +{ + erlang_port = (ErlDrvPort)-1; + return &outputv_driver_entry; +} + +static ErlDrvData outputv_start(ErlDrvPort port, char *buf) +{ + if (erlang_port != (ErlDrvPort)-1) { + return ERL_DRV_ERROR_GENERAL; + } + + erlang_port = port; + return (ErlDrvData)port; +} + +static void outputv_read(ErlDrvData port, char *buf, int count) +{ + erlang_port = (ErlDrvPort)-1; +} + +static void outputv_stop(ErlDrvData port) +{ + erlang_port = (ErlDrvPort)-1; +} + +/* Erts outputv -> drv, echo it back */ +static void outputv(ErlDrvData port, ErlIOVec* ev) +{ + driver_outputv(erlang_port, NULL, 0, ev, 0); +} + + + + + + + + diff --git a/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c b/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c new file mode 100644 index 0000000000..f429a5b51e --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c @@ -0,0 +1,231 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +/* + * Author: Rickard Green + * + * Description: Tests that port I/O queues can be flushed via: + * - ready_input(), + * - ready_output(), + * - timeout(), + * - driver_async() -> read_async(), and + * - event() + */ + +#ifndef UNIX +#if !defined(__WIN32__) && !defined(_OSE_) && !defined(VXWORKS) +#define UNIX 1 +#endif +#endif + +#if defined(DEBUG) || 0 +# define PRINTF(X) printf X +#else +# define PRINTF(X) +#endif + +#if defined(UNIX) +#include <stdio.h> +#include <string.h> +#elif defined(__WIN32__) +#include <windows.h> +#endif + +#include <errno.h> + +#include "erl_driver.h" + +#define PEEK_NONXQ_TEST 0 +#define PEEK_NONXQ_WAIT 1 + +typedef struct { + ErlDrvTermData caller; + ErlDrvPort port; + int cmd; +} PeekNonXQDrvData; + +typedef struct { + ErlDrvPort port; + ErlDrvPDL pdl; +} AsyncData; + +static ErlDrvData start(ErlDrvPort, char *); +static void stop(ErlDrvData); +static int control(ErlDrvData, unsigned int, char *, int, char **, int); +static void ready_async(ErlDrvData, ErlDrvThreadData); +static void async_test(void *); +static void async_wait(void *); +static void async_free(void *); +static void do_sleep(unsigned); + +static ErlDrvEntry peek_non_existing_queue_drv_entry = { + NULL /* init */, + start, + stop, + NULL /* output */, + NULL /* ready_input */, + NULL /* ready_output */, + "peek_non_existing_queue_drv", + NULL /* finish */, + NULL /* handle */, + control, + NULL /* timeout */, + NULL /* outputv */, + ready_async, + NULL /* flush */, + NULL /* call */, + NULL /* event */, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + ERL_DRV_FLAG_USE_PORT_LOCKING, + NULL /* handle2 */, + NULL /* process_exit */ +}; + +DRIVER_INIT(peek_non_existing_queue_drv) +{ + return &peek_non_existing_queue_drv_entry; +} + +static ErlDrvData +start(ErlDrvPort port, char *command) +{ + PeekNonXQDrvData *dp = driver_alloc(sizeof(PeekNonXQDrvData)); + if (!dp) { + errno = ENOMEM; + return ERL_DRV_ERROR_ERRNO; + } + + dp->port = port; + return (ErlDrvData) dp; +} + +static void stop(ErlDrvData drv_data) +{ + driver_free(drv_data); +} + +static int control(ErlDrvData drv_data, + unsigned int command, + char *buf, int len, + char **rbuf, int rlen) +{ + PeekNonXQDrvData *dp = (PeekNonXQDrvData *) drv_data; + unsigned int key = 0; + char *res_str = "ok"; + ErlDrvSysInfo si; + driver_system_info(&si, sizeof(ErlDrvSysInfo)); + if (si.async_threads == 0) { + res_str = "skipped: No async-threads available"; + goto done; + } + + dp->cmd = command; + dp->caller = driver_caller(dp->port); + + switch (command) { + case PEEK_NONXQ_TEST: { + AsyncData *adp = driver_alloc(sizeof(AsyncData)); + if (!adp) { + res_str = "enomem"; + goto done; + } + driver_enq(dp->port, "!", 1); + adp->port = dp->port; + adp->pdl = driver_pdl_create(dp->port); + (void) driver_async(dp->port, &key, async_test, adp, async_free); + break; + } + case PEEK_NONXQ_WAIT: + (void) driver_async(dp->port, &key, async_wait, NULL, NULL); + break; + } + + done: { + int res_len = strlen(res_str); + if (res_len > rlen) { + char *abuf = driver_alloc(sizeof(char)*res_len); + if (!abuf) + return 0; + *rbuf = abuf; + } + + memcpy((void *) *rbuf, (void *) res_str, res_len); + + return res_len; + } +} + +static void ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data) +{ + PeekNonXQDrvData *dp = (PeekNonXQDrvData *) drv_data; + if (dp->cmd == PEEK_NONXQ_WAIT) { + ErlDrvTermData spec[] = { + ERL_DRV_PORT, driver_mk_port(dp->port), + ERL_DRV_ATOM, driver_mk_atom("test_successful"), + ERL_DRV_TUPLE, 2 + }; + driver_send_term(dp->port, + dp->caller, + spec, + sizeof(spec) / sizeof(spec[0])); + } + if (thread_data) + driver_free(thread_data); +} + +static void async_test(void *vadp) +{ + SysIOVec *vec; + int vlen = 4711; + AsyncData *adp = (AsyncData *)vadp; + + do_sleep(1); + + driver_pdl_lock(adp->pdl); + vec = driver_peekq(adp->port, &vlen); + if (vlen >= 0 || vec) + abort(); /* A crude way to fail the test, but what the ... */ + vlen = driver_sizeq(adp->port); + if (vlen >= 0) + abort(); /* ... */ + driver_pdl_unlock(adp->pdl); +} + +static void async_wait(void *vadp) +{ + /* Will always be executed after async_test in the same thread */ +} + + +static void async_free(void *vadp) +{ + driver_free(vadp); +} + +static void +do_sleep(unsigned secs) +{ +#ifdef __WIN32__ + Sleep((DWORD) secs*1000); +#else + sleep(secs); +#endif +} + diff --git a/erts/emulator/test/driver_SUITE_data/queue_drv.c b/erts/emulator/test/driver_SUITE_data/queue_drv.c new file mode 100644 index 0000000000..ded69f89f9 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/queue_drv.c @@ -0,0 +1,195 @@ +#include <stdio.h> +#include "erl_driver.h" + +#define put_int32(i, s) {((char*)(s))[0] = (char)((i) >> 24) & 0xff; \ + ((char*)(s))[1] = (char)((i) >> 16) & 0xff; \ + ((char*)(s))[2] = (char)((i) >> 8) & 0xff; \ + ((char*)(s))[3] = (char)((i) & 0xff);} + +#define get_int32(s) ((((unsigned char*) (s))[0] << 24) | \ + (((unsigned char*) (s))[1] << 16) | \ + (((unsigned char*) (s))[2] << 8) | \ + (((unsigned char*) (s))[3])) + +/* + * Data operations. To use, send code using erlang:port_control/2, + * then send the data to the port. + */ + +#define PUSHQ 0 +#define ENQ 1 +#define PUSHQ_BIN 2 +#define ENQ_BIN 3 +#define PUSHQV 4 +#define ENQV 5 + +/* + * Control operations. Data is returned directly. + */ +#define DEQ 6 +#define BYTES_QUEUED 7 +#define READ_HEAD 8 + +static ErlDrvPort erlang_port; +static unsigned opcode; /* Opcode for next operation. */ +static ErlDrvData queue_start(ErlDrvPort, char*); +static void queue_stop(ErlDrvData), queue_read(ErlDrvData, char*, int); +static void queue_outputv(ErlDrvData, ErlIOVec*); +static int control(ErlDrvData, unsigned int, char*, int, char**, int); +static ErlDrvBinary* read_head(ErlDrvPort, int bytes); + +static ErlDrvEntry queue_driver_entry = +{ + NULL, + queue_start, + queue_stop, + queue_read, + NULL, + NULL, + "queue_drv", + NULL, + NULL, + control, + NULL, + queue_outputv, + NULL +}; + +DRIVER_INIT(queue_drv) +{ + erlang_port = (ErlDrvPort) -1; + return &queue_driver_entry; +} + +static ErlDrvData queue_start(ErlDrvPort port, char *buf) +{ + if (erlang_port != (ErlDrvPort)-1) { + return ERL_DRV_ERROR_GENERAL; + } + erlang_port = port; + opcode = 0xFFFFFFFF; + set_port_control_flags(erlang_port, PORT_CONTROL_FLAG_BINARY); + return (ErlDrvData)port; +} + +/* messages from Erlang */ +static void queue_read(ErlDrvData port, char *buf, int len) +{ +} + +static void queue_stop(ErlDrvData port) +{ + erlang_port = (ErlDrvPort) -1; +} + +static int +control(ErlDrvData drv_data, unsigned command, char* buf, int len, char** rbuf, int rlen) +{ + ErlDrvBinary* b; + + switch (command) { + case PUSHQ: + case ENQ: + case PUSHQ_BIN: + case ENQ_BIN: + case PUSHQV: + case ENQV: + opcode = command; + *rbuf = NULL; + return 0; + case DEQ: + *rbuf = NULL; + if (len != 4) { + driver_failure_atom(erlang_port, "deq: bad length"); + } else { + int n = get_int32(buf); + driver_deq(erlang_port, n); + } + return 0; + case BYTES_QUEUED: + *rbuf = (char*)(b = driver_alloc_binary(4)); + put_int32(driver_sizeq(erlang_port), b->orig_bytes); + return 0; + case READ_HEAD: + if (len != 4) { + driver_failure_atom(erlang_port, "read_head: bad length"); + return 0; + } else { + int n = get_int32(buf); + *rbuf = (char *) read_head(erlang_port, n); + return 0; /* Ignored anyway */ + } + default: + driver_failure_atom(erlang_port, "bad opcode to control()"); + return 0; + } +} + +static void +queue_outputv(ErlDrvData drv_data, ErlIOVec* ev) +{ + ErlDrvBinary* bin; + ErlDrvPort ix = (ErlDrvPort) drv_data; + int i = ev->vsize - 1; + int offset; + + switch (opcode) { + case PUSHQ: + driver_pushq(ix, ev->iov[i].iov_base, ev->iov[i].iov_len); + break; + case ENQ: + driver_enq(ix, ev->iov[i].iov_base, ev->iov[i].iov_len); + break; + case PUSHQ_BIN: + case ENQ_BIN: + if (ev->binv[i] != NULL) { + bin = ev->binv[i]; + offset = ev->iov[i].iov_base - bin->orig_bytes; + } else { + bin = driver_alloc_binary(ev->iov[i].iov_len); + memcpy(bin->orig_bytes, ev->iov[i].iov_base, ev->iov[i].iov_len); + offset = 0; + } + if (opcode == PUSHQ_BIN) { + driver_pushq_bin(ix, bin, offset, ev->iov[i].iov_len); + } else { + driver_enq_bin(ix, bin, offset, ev->iov[i].iov_len); + } + if (ev->binv[i] == NULL) { + driver_free_binary(bin); + } + break; + case PUSHQV: + driver_pushqv(ix, ev, 0); + break; + case ENQV: + driver_enqv(ix, ev, 0); + break; + default: + fprintf(stderr, "[queue_drv] Bad opcode %d\n", opcode); + driver_failure_atom(ix, "bad_opcode"); + break; + } +} + +static ErlDrvBinary* +read_head(ErlDrvPort ix, int bytes) +{ + int len_io_queue; + SysIOVec* iov = driver_peekq(ix, &len_io_queue); + int bytes_left = bytes; + int copied = 0; + ErlDrvBinary* b; + int iv; + + b = driver_alloc_binary(bytes); + iv = 0; + while (bytes_left > 0 && iv < len_io_queue) { + int n = (iov[iv].iov_len < bytes_left) ? iov[iv].iov_len : bytes_left; + memcpy(b->orig_bytes+copied, iov[iv].iov_base, n); + copied += n; + bytes_left -= n; + iv++; + } + return b; +} diff --git a/erts/emulator/test/driver_SUITE_data/smaller_major_vsn_drv.c b/erts/emulator/test/driver_SUITE_data/smaller_major_vsn_drv.c new file mode 100644 index 0000000000..a1299fe807 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/smaller_major_vsn_drv.c @@ -0,0 +1,31 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +/* + * Author: Rickard Green + * + * Description: Implementation of a driver with a smaller major + * driver version than the current system. + */ + +#define VSN_MISMATCH_DRV_NAME_STR "smaller_major_vsn_drv" +#define VSN_MISMATCH_DRV_NAME smaller_major_vsn_drv +#define VSN_MISMATCH_DRV_MAJOR_VSN_DIFF (-1) +#define VSN_MISMATCH_DRV_MINOR_VSN_DIFF 0 + +#include "vsn_mismatch_drv_impl.c" diff --git a/erts/emulator/test/driver_SUITE_data/smaller_minor_vsn_drv.c b/erts/emulator/test/driver_SUITE_data/smaller_minor_vsn_drv.c new file mode 100644 index 0000000000..42b1d2a187 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/smaller_minor_vsn_drv.c @@ -0,0 +1,31 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +/* + * Author: Rickard Green + * + * Description: Implementation of a driver with a smaller minor + * driver version than the current system. + */ + +#define VSN_MISMATCH_DRV_NAME_STR "smaller_minor_vsn_drv" +#define VSN_MISMATCH_DRV_NAME smaller_minor_vsn_drv +#define VSN_MISMATCH_DRV_MAJOR_VSN_DIFF 0 +#define VSN_MISMATCH_DRV_MINOR_VSN_DIFF (-1) + +#include "vsn_mismatch_drv_impl.c" diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_1_0_drv.c b/erts/emulator/test/driver_SUITE_data/sys_info_1_0_drv.c new file mode 100644 index 0000000000..0504778086 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/sys_info_1_0_drv.c @@ -0,0 +1,72 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +/* + * Author: Rickard Green + * + * Description: Driver that fakes driver version 1.0 and tests + * driver_system_info(). + * + */ + +#include "sys_info_drv_impl.h" + +#define SYS_INFO_DRV_MAJOR_VSN 1 +#define SYS_INFO_DRV_MINOR_VSN 0 +#define SYS_INFO_DRV_NAME_STR "sys_info_1_0_drv" +#define SYS_INFO_DRV_NAME sys_info_1_0_drv +#define SYS_INFO_DRV_LAST_FIELD smp_support + +#define SYS_INFO_DRV_RES_FORMAT "ok: " \ + "drv_drv_vsn=%d.%d " \ + "emu_drv_vsn=%d.%d " \ + "erts_vsn=%s " \ + "otp_vsn=%s " \ + "thread=%s " \ + "smp=%s" + + +static size_t +sys_info_drv_max_res_len(ErlDrvSysInfo *sip) +{ + size_t slen = strlen(SYS_INFO_DRV_RES_FORMAT) + 1; + slen += 2*20; /* drv_drv_vsn */ + slen += 2*20; /* emu_drv_vsn */ + slen += strlen(sip->erts_version) + 1; + slen += strlen(sip->otp_release) + 1; + slen += 5; /* threads */ + slen += 5; /* smp */ + return slen; +} + +static size_t +sys_info_drv_sprintf_sys_info(ErlDrvSysInfo *sip, char *str) +{ + return sprintf(str, + SYS_INFO_DRV_RES_FORMAT, + SYS_INFO_DRV_MAJOR_VSN, + SYS_INFO_DRV_MINOR_VSN, + sip->driver_major_version, + sip->driver_minor_version, + sip->erts_version, + sip->otp_release, + sip->thread_support ? "true" : "false", + sip->smp_support ? "true" : "false"); +} + +#include "sys_info_drv_impl.c" diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_1_1_drv.c b/erts/emulator/test/driver_SUITE_data/sys_info_1_1_drv.c new file mode 100644 index 0000000000..fa21828284 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/sys_info_1_1_drv.c @@ -0,0 +1,80 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +/* + * Author: Rickard Green + * + * Description: Driver that fakes driver version 1.1 and tests + * driver_system_info(). + * + */ + +#include "sys_info_drv_impl.h" + +#define SYS_INFO_DRV_MAJOR_VSN 1 +#define SYS_INFO_DRV_MINOR_VSN 1 +#define SYS_INFO_DRV_NAME_STR "sys_info_1_1_drv" +#define SYS_INFO_DRV_NAME sys_info_1_1_drv +#define SYS_INFO_DRV_LAST_FIELD scheduler_threads + +#define SYS_INFO_DRV_RES_FORMAT "ok: " \ + "drv_drv_vsn=%d.%d " \ + "emu_drv_vsn=%d.%d " \ + "erts_vsn=%s " \ + "otp_vsn=%s " \ + "thread=%s " \ + "smp=%s " \ + "async_thrs=%d " \ + "sched_thrs=%d" + + +static size_t +sys_info_drv_max_res_len(ErlDrvSysInfo *sip) +{ + size_t slen = strlen(SYS_INFO_DRV_RES_FORMAT) + 1; + slen += 2*20; /* drv_drv_vsn */ + slen += 2*20; /* emu_drv_vsn */ + slen += strlen(sip->erts_version) + 1; + slen += strlen(sip->otp_release) + 1; + slen += 5; /* threads */ + slen += 5; /* smp */ + slen += 20; /* async_thrs */ + slen += 20; /* sched_thrs */ + return slen; +} + +static size_t +sys_info_drv_sprintf_sys_info(ErlDrvSysInfo *sip, char *str) +{ + return sprintf(str, + SYS_INFO_DRV_RES_FORMAT, + SYS_INFO_DRV_MAJOR_VSN, + SYS_INFO_DRV_MINOR_VSN, + sip->driver_major_version, + sip->driver_minor_version, + sip->erts_version, + sip->otp_release, + sip->thread_support ? "true" : "false", + sip->smp_support ? "true" : "false", + sip->async_threads, + sip->scheduler_threads); +} + +#include "sys_info_drv_impl.c" + + diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_curr_drv.c b/erts/emulator/test/driver_SUITE_data/sys_info_curr_drv.c new file mode 100644 index 0000000000..5bbc966932 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/sys_info_curr_drv.c @@ -0,0 +1,77 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +/* + * Author: Rickard Green + * + * Description: Driver that tests driver_system_info() on current + * driver version. + * + */ + +#include "sys_info_drv_impl.h" + +#define SYS_INFO_DRV_MAJOR_VSN ERL_DRV_EXTENDED_MAJOR_VERSION +#define SYS_INFO_DRV_MINOR_VSN ERL_DRV_EXTENDED_MINOR_VERSION +#define SYS_INFO_DRV_NAME_STR "sys_info_curr_drv" +#define SYS_INFO_DRV_NAME sys_info_curr_drv +#define ERL_DRV_SYS_INFO_SIZE sizeof(ErlDrvSysInfo) + +#define SYS_INFO_DRV_RES_FORMAT "ok: " \ + "drv_drv_vsn=%d.%d " \ + "emu_drv_vsn=%d.%d " \ + "erts_vsn=%s " \ + "otp_vsn=%s " \ + "thread=%s " \ + "smp=%s " \ + "async_thrs=%d " \ + "sched_thrs=%d" + +static size_t +sys_info_drv_max_res_len(ErlDrvSysInfo *sip) +{ + size_t slen = strlen(SYS_INFO_DRV_RES_FORMAT) + 1; + slen += 2*20; /* drv_drv_vsn */ + slen += 2*20; /* emu_drv_vsn */ + slen += strlen(sip->erts_version) + 1; + slen += strlen(sip->otp_release) + 1; + slen += 5; /* threads */ + slen += 5; /* smp */ + slen += 20; /* async_thrs */ + slen += 20; /* sched_thrs */ + return slen; +} + +static size_t +sys_info_drv_sprintf_sys_info(ErlDrvSysInfo *sip, char *str) +{ + return sprintf(str, + SYS_INFO_DRV_RES_FORMAT, + SYS_INFO_DRV_MAJOR_VSN, + SYS_INFO_DRV_MINOR_VSN, + sip->driver_major_version, + sip->driver_minor_version, + sip->erts_version, + sip->otp_release, + sip->thread_support ? "true" : "false", + sip->smp_support ? "true" : "false", + sip->async_threads, + sip->scheduler_threads); +} + +#include "sys_info_drv_impl.c" diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c b/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c new file mode 100644 index 0000000000..2d3203ae5d --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c @@ -0,0 +1,154 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +/* + * Author: Rickard Green + * + * Description: Implementation of a driver that fakes different driver + * versions and tests driver_system_info(). This file should + * be included by an implementation that defines: + * * SYS_INFO_DRV_MAJOR_VSN + * * SYS_INFO_DRV_MINOR_VSN + * * SYS_INFO_DRV_NAME_STR + * * SYS_INFO_DRV_NAME + * * ERL_DRV_SYS_INFO_SIZE, or SYS_INFO_DRV_LAST_FIELD + * and implements: + * * static size_t sys_info_drv_max_res_len(ErlDrvSysInfo *) + * * static size_t sys_info_drv_sprintf_sys_info(ErlDrvSysInfo *, + * char *) + * + */ + +#if !defined(ERL_DRV_SYS_INFO_SIZE) && defined(SYS_INFO_DRV_LAST_FIELD) + +#define ERL_DRV_SYS_INFO_SIZE_FROM_LAST_FIELD(LAST_FIELD) \ + (((size_t) &((ErlDrvSysInfo *) 0)->LAST_FIELD) \ + + sizeof(((ErlDrvSysInfo *) 0)->LAST_FIELD)) + +#define ERL_DRV_SYS_INFO_SIZE \ + ERL_DRV_SYS_INFO_SIZE_FROM_LAST_FIELD(SYS_INFO_DRV_LAST_FIELD) + +#endif + +static ErlDrvData start(ErlDrvPort, char *); +static int control(ErlDrvData, unsigned int, char *, int, char **, int); + +static ErlDrvEntry drv_entry = { + NULL /* init */, + start, + NULL /* stop */, + NULL /* output */, + NULL /* ready_input */, + NULL /* ready_output */, + SYS_INFO_DRV_NAME_STR, + NULL /* finish */, + NULL /* handle */, + control, + NULL /* timeout */, + NULL /* outputv */, + NULL /* ready_async */, + NULL /* flush */, + NULL /* call */, + NULL /* event */, + ERL_DRV_EXTENDED_MARKER, + SYS_INFO_DRV_MAJOR_VSN, + SYS_INFO_DRV_MINOR_VSN, + ERL_DRV_FLAG_USE_PORT_LOCKING, + NULL /* handle2 */, + NULL /* process_exit */ +}; + +DRIVER_INIT(SYS_INFO_DRV_NAME) +{ + return &drv_entry; +} + +static ErlDrvData +start(ErlDrvPort port, char *command) +{ + return (ErlDrvData) port; +} + +static int +control(ErlDrvData drv_data, + unsigned int command, + char *buf, int len, + char **rbuf, int rlen) +{ + int res; + char *str; + size_t slen, slen2; + ErlDrvPort port = (ErlDrvPort) drv_data; + unsigned deadbeef[] = {0xdeadbeef, + 0xdeadbeef, + 0xdeadbeef, + 0xdeadbeef, + 0xdeadbeef, + 0xdeadbeef, + 0xdeadbeef, + 0xdeadbeef, + 0xdeadbeef, + 0xdeadbeef}; + ErlDrvSysInfo *sip = driver_alloc(ERL_DRV_SYS_INFO_SIZE + sizeof(deadbeef)); + char *beyond_end_format = "error: driver_system_info() wrote beyond end " + "of the ErlDrvSysInfo struct"; + char *buf_overflow_format = "error: Internal buffer overflow"; + + if (!sip) { + driver_failure_atom(port, "enomem"); + return 0; + } + + memset((char *) sip, 0xed, ERL_DRV_SYS_INFO_SIZE); + memcpy(((char *) sip) + ERL_DRV_SYS_INFO_SIZE, + (char *) &deadbeef[0], + sizeof(deadbeef)); + + driver_system_info(sip, ERL_DRV_SYS_INFO_SIZE); + + slen = sys_info_drv_max_res_len(sip); + slen2 = strlen(beyond_end_format) + 1; + if (slen2 > slen) + slen = slen2; + slen2 = strlen(buf_overflow_format) + 1; + if (slen2 > slen) + slen = slen2; + str = driver_alloc(slen); + if (!str) { + driver_free(sip); + driver_failure_atom(port, "enomem"); + return 0; + } + *rbuf = str; + + /* Check that the emulator didn't write beyond ERL_DRV_SYS_INFO_SIZE */ + if (memcmp(((char *) sip) + ERL_DRV_SYS_INFO_SIZE, + (char *) &deadbeef[0], + sizeof(deadbeef)) != 0) { + res = sprintf(str, beyond_end_format); + } + else { + res = sys_info_drv_sprintf_sys_info(sip, str); + if (res > slen) + res = sprintf(str, buf_overflow_format); + } + driver_free(sip); + return res; +} + + diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.h b/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.h new file mode 100644 index 0000000000..5a6ddb15cf --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.h @@ -0,0 +1,29 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +/* + * Author: Rickard Green + * + * Description: Header file used by 'sys_info_drv's. + * + */ + +#include <stdio.h> +#include <string.h> +#include "erl_driver.h" + diff --git a/erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c b/erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c new file mode 100644 index 0000000000..c7edbba7f6 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c @@ -0,0 +1,125 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include "erl_driver.h" + +ErlDrvData start(ErlDrvPort port, char *command); +int control(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen); + +static int call(ErlDrvData drv_data, + unsigned int command, + char *buf, int len, + char **rbuf, int rlen, + unsigned int *flags); + +static ErlDrvEntry thr_alloc_drv_entry = { + NULL /* init */, + start, + NULL /* stop */, + NULL /* output */, + NULL /* ready_input */, + NULL /* ready_output */, + "thr_alloc_drv", + NULL /* finish */, + NULL /* handle */, + control, + NULL /* timeout */, + NULL /* outputv */, + NULL /* ready_async */, + NULL /* flush */, + NULL /* call */, + NULL /* event */, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + ERL_DRV_FLAG_USE_PORT_LOCKING, + NULL /* handle2 */, + NULL /* handle_monitor */ +}; + +DRIVER_INIT(thr_alloc_drv) +{ + return &thr_alloc_drv_entry; +} + +void * +test_thread(void *vsize) +{ + int i; + int size = (int) (long) vsize; + void *mem; + mem = driver_alloc(size); + if (mem) + driver_free(mem); +} + +ErlDrvData start(ErlDrvPort port, char *command) +{ + return (ErlDrvData) port; +} + +int control(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen) +{ + ErlDrvPort port = (ErlDrvPort) drv_data; + char *result = "failure"; + int result_len; + if (len <= 20) { + int res; + ErlDrvTid tid; + char ibuf[21]; + int size; + memcpy((void *) ibuf, buf, len); + ibuf[len] = '\0'; + size = atoi(ibuf); + if (size > 0) { + res = erl_drv_thread_create("test_thread", + &tid, + test_thread, + (void *) (long) size, + NULL); + if (res == 0) { + res = erl_drv_thread_join(tid, NULL); + if (res == 0) + result = "ok"; + } + if (res != 0) + driver_failure_posix(port, res); + } + } + + result_len = strlen(result); + if (result_len <= rlen) { + memcpy(*rbuf, result, result_len); + return result_len; + } + else { + *rbuf = driver_alloc(result_len); + if (!*rbuf) { + driver_failure_posix(port, ENOMEM); + return 0; + } + else { + memcpy(*rbuf, result, result_len); + return result_len; + } + } +} diff --git a/erts/emulator/test/driver_SUITE_data/timer_drv.c b/erts/emulator/test/driver_SUITE_data/timer_drv.c new file mode 100644 index 0000000000..b96a95dd4c --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/timer_drv.c @@ -0,0 +1,96 @@ +#ifdef VXWORKS +#include <vxWorks.h> +#include <taskVarLib.h> +#include <taskLib.h> +#include <sysLib.h> +#include <string.h> +#include <ioLib.h> +#endif +#include <stdio.h> +#include "erl_driver.h" + +#define get_int32(s) ((((unsigned char*) (s))[0] << 24) | \ + (((unsigned char*) (s))[1] << 16) | \ + (((unsigned char*) (s))[2] << 8) | \ + (((unsigned char*) (s))[3])) + +#define START_TIMER 0 +#define CANCEL_TIMER 1 +#define DELAY_START_TIMER 2 +#define TIMER 3 +#define CANCELLED 4 + +static ErlDrvPort erlang_port; +static ErlDrvData timer_start(ErlDrvPort, char*); +static void timer_stop(ErlDrvData), timer_read(ErlDrvData, char*, int), timer(ErlDrvData); + +static ErlDrvEntry timer_driver_entry = +{ + NULL, + timer_start, + timer_stop, + timer_read, + NULL, + NULL, + "timer_drv", + NULL, + NULL, + NULL, + timer, + NULL, + NULL +}; + +DRIVER_INIT(timer_drv) +{ + erlang_port = (ErlDrvPort)-1; + return &timer_driver_entry; +} + +static ErlDrvData timer_start(ErlDrvPort port, char *buf) +{ + if (erlang_port != (ErlDrvPort)-1) { + return ERL_DRV_ERROR_GENERAL; + } + erlang_port = port; + return (ErlDrvData)port; +} + +/* set the timer, this is monitored from erlang measuring the time */ +static void timer_read(ErlDrvData port, char *buf, int len) +{ + char reply[1]; + + if (buf[0] == START_TIMER) { + /* fprintf(stderr, "[timer_drv] Setting timeout: %i\n", get_int32(buf + 1)); */ + driver_set_timer(port, get_int32(buf + 1)); + } else if (buf[0] == CANCEL_TIMER) { + /* fprintf(stderr, "[timer_drv] Timer cancelled\n"); */ + driver_cancel_timer(port); + reply[0] = CANCELLED; + driver_output(port, reply, 1); + } else if (buf[0] == DELAY_START_TIMER) { +#ifndef __WIN32__ +#ifdef VXWORKS + taskDelay(sysClkRateGet()); +#else + sleep(1); +#endif +#endif + driver_set_timer(port, get_int32(buf + 1)); + } +} + +static void timer_stop(ErlDrvData port) +{ + erlang_port = (ErlDrvPort)-1; +} + +static void timer(ErlDrvData port) +{ + char reply[1]; + + /* fprintf(stderr, "[timer_drv] timer timed out\n"); */ + reply[0] = TIMER; + driver_output((ErlDrvPort)port, reply, 1); +} diff --git a/erts/emulator/test/driver_SUITE_data/vsn_mismatch_drv_impl.c b/erts/emulator/test/driver_SUITE_data/vsn_mismatch_drv_impl.c new file mode 100644 index 0000000000..53b0a029ce --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/vsn_mismatch_drv_impl.c @@ -0,0 +1,67 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +/* + * Author: Rickard Green + * + * Description: Implementation of a driver that fakes driver version. It + * is used for checking that version mismatches are handled + * correct by the emulator. The following makros have to be + * defined before it can be used: + * * VSN_MISMATCH_DRV_NAME_STR + * * VSN_MISMATCH_DRV_NAME + * * VSN_MISMATCH_DRV_MAJOR_VSN_DIFF + * * VSN_MISMATCH_DRV_MINOR_VSN_DIFF + */ + +#include "erl_driver.h" + +static ErlDrvEntry drv_entry = { + NULL /* init */, + NULL /* start */, + NULL /* stop */, + NULL /* output */, + NULL /* ready_input */, + NULL /* ready_output */, + VSN_MISMATCH_DRV_NAME_STR, + NULL /* finish */, + NULL /* handle */, + NULL /* control */, + NULL /* timeout */, + NULL /* outputv */, + NULL /* ready_async */, + NULL /* flush */, + NULL /* call */, + NULL /* event */, +#ifdef VSN_MISMATCH_DRV_EXTENDED_MARKER + VSN_MISMATCH_DRV_EXTENDED_MARKER, +#else + ERL_DRV_EXTENDED_MARKER, +#endif + ERL_DRV_EXTENDED_MAJOR_VERSION + VSN_MISMATCH_DRV_MAJOR_VSN_DIFF, + ERL_DRV_EXTENDED_MINOR_VERSION + VSN_MISMATCH_DRV_MINOR_VSN_DIFF, + ERL_DRV_FLAG_USE_PORT_LOCKING, + NULL /* handle2 */, + NULL /* process_exit */ +}; + +DRIVER_INIT(VSN_MISMATCH_DRV_NAME) +{ + return &drv_entry; +} + diff --git a/erts/emulator/test/driver_SUITE_data/zero_extended_marker_garb_drv.c b/erts/emulator/test/driver_SUITE_data/zero_extended_marker_garb_drv.c new file mode 100644 index 0000000000..ed705e565f --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/zero_extended_marker_garb_drv.c @@ -0,0 +1,32 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +/* + * Author: Rickard Green + * + * Description: Implementation of a driver with an invalid extended + * marker. + */ + +#define VSN_MISMATCH_DRV_EXTENDED_MARKER 0 +#define VSN_MISMATCH_DRV_NAME_STR "zero_extended_marker_garb_drv" +#define VSN_MISMATCH_DRV_NAME zero_extended_marker_garb_drv +#define VSN_MISMATCH_DRV_MAJOR_VSN_DIFF 0 +#define VSN_MISMATCH_DRV_MINOR_VSN_DIFF 0 + +#include "vsn_mismatch_drv_impl.c" diff --git a/erts/emulator/test/efile_SUITE.erl b/erts/emulator/test/efile_SUITE.erl new file mode 100644 index 0000000000..1d66b6ef70 --- /dev/null +++ b/erts/emulator/test/efile_SUITE.erl @@ -0,0 +1,76 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(efile_SUITE). +-export([all/1]). +-export([iter_max_files/1]). + +-include("test_server.hrl"). + +all(suite) -> [iter_max_files]. + +%% +%% Open as many files as possible. Do this several times and check +%% that we get the same number of files every time. +%% + +iter_max_files(suite) -> []; +iter_max_files(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir,Config), + ?line TestFile = filename:join(DataDir, "existing_file"), + ?line L = do_iter_max_files(10, TestFile), + ?line io:format("Number of files opened in each test:~n~w\n", [L]), + ?line all_equal(L), + Head = hd(L), + if Head >= 2 -> ok; + true -> ?line test_server:fail(too_few_files) + end, + {comment, "Max files: " ++ integer_to_list(hd(L))}. + +do_iter_max_files(N, Name) when N > 0 -> + ?line [max_files(Name)| do_iter_max_files(N-1, Name)]; +do_iter_max_files(_, _) -> + []. + +all_equal([E, E| T]) -> + ?line all_equal([E| T]); +all_equal([_]) -> + ok; +all_equal([]) -> + ok. + +max_files(Name) -> + ?line Fds = open_files(Name), + ?line N = length(Fds), + ?line close_files(Fds), + N. + +close_files([Fd| Fds]) -> + ?line file:close(Fd), + ?line close_files(Fds); +close_files([]) -> + ok. + +open_files(Name) -> + ?line case file:open(Name, [read,raw]) of + {ok, Fd} -> + [Fd| open_files(Name)]; + {error, Reason} -> + io:format("Error reason: ~p", [Reason]), + [] + end. diff --git a/erts/emulator/test/efile_SUITE_data/existing_file b/erts/emulator/test/efile_SUITE_data/existing_file new file mode 100644 index 0000000000..540c89611b --- /dev/null +++ b/erts/emulator/test/efile_SUITE_data/existing_file @@ -0,0 +1 @@ +This file must exist, but its contents is not important. diff --git a/erts/emulator/test/emulator.spec b/erts/emulator/test/emulator.spec new file mode 100644 index 0000000000..ed5bd48e84 --- /dev/null +++ b/erts/emulator/test/emulator.spec @@ -0,0 +1 @@ +{topcase, {dir, "../emulator_test"}}. diff --git a/erts/emulator/test/emulator.spec.ose b/erts/emulator/test/emulator.spec.ose new file mode 100644 index 0000000000..9f494609d9 --- /dev/null +++ b/erts/emulator/test/emulator.spec.ose @@ -0,0 +1,2 @@ +{topcase, {dir, "../emulator_test"}}. +{skip, {obsolete_SUITE, "Not on ose"}}. diff --git a/erts/emulator/test/emulator.spec.vxworks b/erts/emulator/test/emulator.spec.vxworks new file mode 100644 index 0000000000..55675bdc29 --- /dev/null +++ b/erts/emulator/test/emulator.spec.vxworks @@ -0,0 +1,26 @@ +{topcase, {dir, "../emulator_test"}}. + +% Added since R11 +{skip,{distribution_SUITE,link_to_dead_new_node,"Does not work in distributed test environments"}}. +{skip,{binary_SUITE,terms_float,"Floats, VxWorks, PPC = Floating points never equal..."}}. +{skip,{system_info_SUITE,process_count,"Fix-allocs starving VxWorks cards"}}. +{skip,{monitor_SUITE,mixer,"Fix-allocs starving VxWorks cards"}}. + +{skip,{node_container_SUITE,"Too memory consuming..."}}. + +{skip,{trace_SUITE,system_monitor_long_gc_1,"Too memory consuming..."}}. +{skip,{trace_SUITE,system_monitor_long_gc_2,"Too memory consuming..."}}. +{skip,{trace_SUITE,system_monitor_large_heap_1,"Too memory consuming..."}}. +{skip,{trace_SUITE,system_monitor_large_heap_2,"Too memory consuming..."}}. +% End added since R11 + +{skip, {distribution_SUITE,stop_dist,"Not written to work on VxWorks."}}. +{skip, {distribution_SUITE,dist_auto_connect_never, + "Not written to work on VxWorks."}}. +{skip, {distribution_SUITE,dist_auto_connect_once, + "Not written to work on VxWorks."}}. +{skip, {trace_SUITE,system_monitor_long_gc, + "Too memory consuming for VxWorks cards."}}. +{skip, {trace_meta_SUITE,stack_grow, + "Too memory consuming for VxWorks cards."}}. +{skip, {obsolete_SUITE, "Not on vxworks"}}. diff --git a/erts/emulator/test/emulator.spec.win b/erts/emulator/test/emulator.spec.win new file mode 100644 index 0000000000..6181a36358 --- /dev/null +++ b/erts/emulator/test/emulator.spec.win @@ -0,0 +1,2 @@ +{topcase, {dir, "../emulator_test"}}. +{skip, {obsolete_SUITE, "Not on windows"}}. diff --git a/erts/emulator/test/erl_drv_thread_SUITE.erl b/erts/emulator/test/erl_drv_thread_SUITE.erl new file mode 100644 index 0000000000..ea618e9feb --- /dev/null +++ b/erts/emulator/test/erl_drv_thread_SUITE.erl @@ -0,0 +1,119 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(erl_drv_thread_SUITE). +-author('[email protected]'). +-export([all/1]). + +-export([basic/1, rwlock/1, tsd/1]). + +-include("test_server.hrl"). + +-define(DEFAULT_TIMETRAP_SECS, 240). + +all(doc) -> []; +all(suite) -> + [basic, rwlock, tsd]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %% +%% Testcases %% +%% %% + +basic(suite) -> []; +basic(doc) -> []; +basic(Cfg) -> ?line drv_case(Cfg, basic). + +rwlock(suite) -> []; +rwlock(doc) -> []; +rwlock(Cfg) -> ?line drv_case(Cfg, rwlock). + +tsd(suite) -> []; +tsd(doc) -> []; +tsd(Cfg) -> ?line drv_case(Cfg, tsd). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %% +%% Internal functions %% +%% %% + +drv_case(Config, CaseName) -> + drv_case(Config, CaseName, ""). + +drv_case(Config, CaseName, TimeTrap) when is_integer(TimeTrap) -> + drv_case(Config, CaseName, "", TimeTrap); +drv_case(Config, CaseName, Command) when is_list(Command) -> + drv_case(Config, CaseName, Command, ?DEFAULT_TIMETRAP_SECS). + +drv_case(Config, CaseName, TimeTrap, Command) when is_list(Command), + is_integer(TimeTrap) -> + drv_case(Config, CaseName, Command, TimeTrap); +drv_case(Config, CaseName, Command, TimeTrap) when is_list(Config), + is_atom(CaseName), + is_list(Command), + is_integer(TimeTrap) -> + case ?t:os_type() of + {Family, _} when Family == unix; Family == win32 -> + ?line run_drv_case(Config, CaseName, Command, TimeTrap); + SkipOs -> + ?line {skipped, + lists:flatten(["Not run on " + | io_lib:format("~p",[SkipOs])])} + end. + +run_drv_case(Config, CaseName, Command, TimeTrap) -> + ?line Dog = test_server:timetrap(test_server:seconds(TimeTrap)), + ?line DataDir = ?config(data_dir,Config), + case erl_ddll:load_driver(DataDir, CaseName) of + ok -> ok; + {error, Error} -> + io:format("~s\n", [erl_ddll:format_error(Error)]), + ?line ?t:fail() + end, + ?line Port = open_port({spawn, atom_to_list(CaseName)}, []), + ?line true = is_port(Port), + ?line Port ! {self(), {command, Command}}, + ?line Result = receive_drv_result(Port, CaseName), + ?line Port ! {self(), close}, + ?line receive + {Port, closed} -> + ok + end, + ?line ok = erl_ddll:unload_driver(CaseName), + ?line test_server:timetrap_cancel(Dog), + ?line Result. + +receive_drv_result(Port, CaseName) -> + ?line receive + {print, Port, CaseName, Str} -> + ?line ?t:format("~s", [Str]), + ?line receive_drv_result(Port, CaseName); + {'EXIT', Port, Error} -> + ?line ?t:fail(Error); + {'EXIT', error, Error} -> + ?line ?t:fail(Error); + {failed, Port, CaseName, Comment} -> + ?line ?t:fail(Comment); + {skipped, Port, CaseName, Comment} -> + ?line {skipped, Comment}; + {succeeded, Port, CaseName, ""} -> + ?line succeeded; + {succeeded, Port, CaseName, Comment} -> + ?line {comment, Comment} + end. diff --git a/erts/emulator/test/erl_drv_thread_SUITE_data/Makefile.src b/erts/emulator/test/erl_drv_thread_SUITE_data/Makefile.src new file mode 100644 index 0000000000..216707e8a5 --- /dev/null +++ b/erts/emulator/test/erl_drv_thread_SUITE_data/Makefile.src @@ -0,0 +1,33 @@ +# ``The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved via the world wide web at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# The Initial Developer of the Original Code is Ericsson Utvecklings AB. +# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings +# AB. All Rights Reserved.'' +# +# $Id$ +# + +TEST_DRVS = basic@dll@ rwlock@dll@ tsd@dll@ +CC = @CC@ +LD = @LD@ +CFLAGS = @SHLIB_CFLAGS@ -I@erl_include@ @DEFS@ +SHLIB_EXTRA_LDLIBS = testcase_driver@obj@ + +all: $(TEST_DRVS) + +@SHLIB_RULES@ + +testcase_driver@obj@: testcase_driver.c testcase_driver.h +$(TEST_DRVS): testcase_driver@obj@ + + + diff --git a/erts/emulator/test/erl_drv_thread_SUITE_data/basic.c b/erts/emulator/test/erl_drv_thread_SUITE_data/basic.c new file mode 100644 index 0000000000..fca2c1dbea --- /dev/null +++ b/erts/emulator/test/erl_drv_thread_SUITE_data/basic.c @@ -0,0 +1,291 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" + +#ifdef __WIN32__ +#include <windows.h> +#else +#include <unistd.h> +#endif +#include <errno.h> + +#define NO_OF_THREADS 2 + +static int die; +static int cw_passed; +static int res_tf0; +static int res_tf1; +static ErlDrvMutex *mtx; +static ErlDrvCond *cnd; +static int need_join[NO_OF_THREADS]; +static ErlDrvTid tid[NO_OF_THREADS]; +static ErlDrvThreadOpts *topts; + +typedef struct { + int n; +} thr_arg_t; + +static void +do_sleep(unsigned secs) +{ +#ifdef __WIN32__ + Sleep((DWORD) secs*1000); +#else + sleep(secs); +#endif +} + +static void *tf0(void *vta) +{ + if (((thr_arg_t *) vta)->n == 0) { + + erl_drv_mutex_lock(mtx); + + erl_drv_cond_wait(cnd, mtx); + + if (die) { + erl_drv_mutex_unlock(mtx); + return NULL; + } + + cw_passed++; + + erl_drv_cond_wait(cnd, mtx); + + if (die) { + erl_drv_mutex_unlock(mtx); + return NULL; + } + + cw_passed++; + + erl_drv_mutex_unlock(mtx); + if (erl_drv_equal_tids(erl_drv_thread_self(), tid[0])) + res_tf0 = 0; + } + + return (void *) &res_tf0; +} + + +static void *tf1(void *vta) +{ + + if (((thr_arg_t *) vta)->n == 1) { + + erl_drv_mutex_lock(mtx); + + erl_drv_cond_wait(cnd, mtx); + + if (die) { + erl_drv_mutex_unlock(mtx); + return NULL; + } + + cw_passed++; + + erl_drv_cond_wait(cnd, mtx); + + if (die) { + erl_drv_mutex_unlock(mtx); + return NULL; + } + + cw_passed++; + + erl_drv_mutex_unlock(mtx); + + if (erl_drv_equal_tids(erl_drv_thread_self(), tid[1])) + res_tf1 = 1; + + erl_drv_thread_exit((void *) &res_tf1); + + res_tf1 = 4711; + } + return NULL; +} + +void +testcase_run(TestCaseState_t *tcs) +{ + int i, r; + void *tres[2]; + thr_arg_t ta[2]; + ErlDrvTid my_tid; + ErlDrvSysInfo sinfo; + + driver_system_info(&sinfo, sizeof(ErlDrvSysInfo)); + if (!sinfo.thread_support) + testcase_skipped(tcs, "No thread support; nothing to test"); + + testcase_printf(tcs, "Initializing\n"); + + cw_passed = 0; + die = 0; + my_tid = erl_drv_thread_self(); + + for (i = 0; i < NO_OF_THREADS; i++) + need_join[i] = 0; + + res_tf0 = 17; + res_tf1 = 17; + + mtx = NULL; + cnd = NULL; + /* Create mutex and cond */ + mtx = erl_drv_mutex_create("mutex"); + ASSERT(tcs, mtx); + cnd = erl_drv_cond_create("cond"); + ASSERT(tcs, cnd); + topts = erl_drv_thread_opts_create("thread opts"); + ASSERT(tcs, topts); + topts->suggested_stack_size = 0; /* As small as possible */ + + testcase_printf(tcs, "Creating threads 0 & 1\n"); + + /* Create the threads */ + ta[0].n = 0; + r = erl_drv_thread_create("thread 0", &tid[0], tf0, (void *) &ta[0], topts); + ASSERT(tcs, r == 0); + need_join[0] = 1; + + ta[1].n = 1; + r = erl_drv_thread_create("thread 1", &tid[1], tf1, (void *) &ta[1], NULL); + ASSERT(tcs, r == 0); + need_join[1] = 1; + + testcase_printf(tcs, "Testing tids\n"); + + ASSERT(tcs, !erl_drv_equal_tids(tid[0], my_tid)); + ASSERT(tcs, !erl_drv_equal_tids(tid[1], my_tid)); + ASSERT(tcs, !erl_drv_equal_tids(tid[0], tid[1])); + ASSERT(tcs, erl_drv_equal_tids(my_tid, erl_drv_thread_self())); + + testcase_printf(tcs, "Testing mutex/cond\n"); + + /* Make sure the threads waits on cond wait */ + do_sleep(1); + + erl_drv_mutex_lock(mtx); + + ASSERT_CLNUP(tcs, cw_passed == 0, erl_drv_mutex_unlock(mtx)); + + /* Let one thread pass one cond wait */ + erl_drv_cond_signal(cnd); + + erl_drv_mutex_unlock(mtx); + + do_sleep(1); + + erl_drv_mutex_lock(mtx); + + ASSERT_CLNUP(tcs, cw_passed == 1, erl_drv_mutex_unlock(mtx)); + + + /* Let both threads pass one cond wait */ + erl_drv_cond_broadcast(cnd); + + erl_drv_mutex_unlock(mtx); + + do_sleep(1); + + erl_drv_mutex_lock(mtx); + + ASSERT_CLNUP(tcs, cw_passed == 3, erl_drv_mutex_unlock(mtx)); + + + /* Let the thread that only have passed one cond wait pass the other one */ + erl_drv_cond_signal(cnd); + + erl_drv_mutex_unlock(mtx); + + do_sleep(1); + + erl_drv_mutex_lock(mtx); + + ASSERT_CLNUP(tcs, cw_passed == 4, erl_drv_mutex_unlock(mtx)); + + + testcase_printf(tcs, "Testing join\n"); + + /* Both threads should have passed both cond waits and exited; + join them and check returned values */ + + erl_drv_thread_join(tid[0], &tres[0]); + ASSERT_CLNUP(tcs, r == 0, erl_drv_mutex_unlock(mtx)); + need_join[0] = 0; + + ASSERT_CLNUP(tcs, tres[0] == &res_tf0, erl_drv_mutex_unlock(mtx)); + ASSERT_CLNUP(tcs, res_tf0 == 0, erl_drv_mutex_unlock(mtx)); + + r = erl_drv_thread_join(tid[1], &tres[1]); + ASSERT_CLNUP(tcs, r == 0, erl_drv_mutex_unlock(mtx)); + need_join[1] = 0; + + ASSERT_CLNUP(tcs, tres[1] == &res_tf1, erl_drv_mutex_unlock(mtx)); + ASSERT_CLNUP(tcs, res_tf1 == 1, erl_drv_mutex_unlock(mtx)); + + /* Test signaling when noone waits */ + + erl_drv_cond_signal(cnd); + + /* Test broadcasting when noone waits */ + + erl_drv_cond_broadcast(cnd); + + erl_drv_mutex_unlock(mtx); + + erl_drv_mutex_destroy(mtx); + mtx = NULL; + + erl_drv_cond_destroy(cnd); + cnd = NULL; + + erl_drv_thread_opts_destroy(topts); + topts = NULL; + + testcase_printf(tcs, "done\n"); +} + +char * +testcase_name(void) +{ + return "basic"; +} + +void +testcase_cleanup(TestCaseState_t *tcs) +{ + int i; + for (i = 0; i < NO_OF_THREADS; i++) { + if (need_join[i]) { + erl_drv_mutex_lock(mtx); + die = 1; + erl_drv_cond_broadcast(cnd); + erl_drv_mutex_unlock(mtx); + erl_drv_thread_join(tid[i], NULL); + } + } + if (mtx) + erl_drv_mutex_destroy(mtx); + if (cnd) + erl_drv_cond_destroy(cnd); + if (topts) + erl_drv_thread_opts_destroy(topts); +} diff --git a/erts/emulator/test/erl_drv_thread_SUITE_data/rwlock.c b/erts/emulator/test/erl_drv_thread_SUITE_data/rwlock.c new file mode 100644 index 0000000000..064f52c16b --- /dev/null +++ b/erts/emulator/test/erl_drv_thread_SUITE_data/rwlock.c @@ -0,0 +1,214 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" + +#ifdef __WIN32__ +#include <windows.h> +#else +#include <unistd.h> +#endif +#include <errno.h> + +#define NO_OF_THREADS 17 + +struct { + int alive; + ErlDrvTid tid; +} test_thr[NO_OF_THREADS] = {0}; + + +static int die; +static int ready; +static int rlocked; +static int rwlocked; +static int do_rlock; +static int do_rwlock; +static ErlDrvMutex *mtx; +static ErlDrvCond *cnd; +static ErlDrvRWLock *rwlck; + +static void +do_sleep(unsigned secs) +{ +#ifdef __WIN32__ + Sleep((DWORD) secs*1000); +#else + sleep(secs); +#endif +} + +static void *tf(void *unused) +{ + + erl_drv_mutex_lock(mtx); + ready++; + if (ready == NO_OF_THREADS) + erl_drv_cond_broadcast(cnd); + while (!do_rlock) + erl_drv_cond_wait(cnd, mtx); + erl_drv_mutex_unlock(mtx); + + erl_drv_rwlock_rlock(rwlck); + + /* make sure everyone rlocks at the same time */ + erl_drv_mutex_lock(mtx); + rlocked++; + if (rlocked == NO_OF_THREADS) + erl_drv_cond_broadcast(cnd); + while (rlocked != NO_OF_THREADS && !die) + erl_drv_cond_wait(cnd, mtx); + erl_drv_mutex_unlock(mtx); + + erl_drv_rwlock_runlock(rwlck); + + erl_drv_mutex_lock(mtx); + while (!do_rwlock && !die) + erl_drv_cond_wait(cnd, mtx); + if (die) { + erl_drv_mutex_unlock(mtx); + return NULL; + } + erl_drv_mutex_unlock(mtx); + + erl_drv_rwlock_rwlock(rwlck); + rwlocked++; + erl_drv_rwlock_rwunlock(rwlck); + + return NULL; +} + +void +testcase_run(TestCaseState_t *tcs) +{ + int i, r; + ErlDrvSysInfo sinfo; + + driver_system_info(&sinfo, sizeof(ErlDrvSysInfo)); + if (!sinfo.thread_support) + testcase_skipped(tcs, "No thread support; nothing to test"); + + testcase_printf(tcs, "Initializing\n"); + die = 0; + ready = 0; + rlocked = 0; + rwlocked = 0; + do_rlock = 0; + do_rwlock = 0; + + mtx = erl_drv_mutex_create("test mutex"); + cnd = erl_drv_cond_create("test cond"); + rwlck = erl_drv_rwlock_create("test rwlock"); + ASSERT(tcs, mtx && cnd && rwlck); + + testcase_printf(tcs, "Creating %d threads\n", NO_OF_THREADS); + /* Create the threads */ + for (i = 0; i < NO_OF_THREADS; i++) { + char name[100]; + sprintf(name, "thread %d", i); + r = erl_drv_thread_create(name, + &test_thr[i].tid, + tf, + NULL, + NULL); + ASSERT(tcs, r == 0); + test_thr[i].alive = 1; + } + + testcase_printf(tcs, "Testing\n"); + erl_drv_rwlock_rwlock(rwlck); + + erl_drv_mutex_lock(mtx); + while (ready != NO_OF_THREADS) + erl_drv_cond_wait(cnd, mtx); + do_rlock = 1; + erl_drv_cond_broadcast(cnd); + erl_drv_mutex_unlock(mtx); + + do_sleep(1); + + erl_drv_mutex_lock(mtx); + + ASSERT_CLNUP(tcs, + rlocked == 0, + do { + erl_drv_mutex_unlock(mtx); + erl_drv_rwlock_rwunlock(rwlck); + } while (0)); + + erl_drv_mutex_unlock(mtx); + erl_drv_rwlock_rwunlock(rwlck); + + do_sleep(2); + + erl_drv_mutex_lock(mtx); + ASSERT_CLNUP(tcs, rlocked == NO_OF_THREADS, erl_drv_mutex_unlock(mtx)); + do_rwlock = 1; + erl_drv_cond_broadcast(cnd); + erl_drv_mutex_unlock(mtx); + + testcase_printf(tcs, "Joining threads\n"); + /* Join the threads */ + for (i = 0; i < NO_OF_THREADS; i++) { + void *res; + r = erl_drv_thread_join(test_thr[i].tid, NULL); + test_thr[i].alive = 0; + ASSERT(tcs, r == 0); + } + + erl_drv_mutex_lock(mtx); + ASSERT_CLNUP(tcs, rwlocked == NO_OF_THREADS, erl_drv_mutex_unlock(mtx)); + erl_drv_mutex_unlock(mtx); + + erl_drv_mutex_destroy(mtx); + mtx = NULL; + erl_drv_cond_destroy(cnd); + cnd = NULL; + erl_drv_rwlock_destroy(rwlck); + rwlck = NULL; + + testcase_printf(tcs, "done\n"); +} + +char * +testcase_name(void) +{ + return "rwlock"; +} + +void +testcase_cleanup(TestCaseState_t *tcs) +{ + int i; + for (i = 0; i < NO_OF_THREADS; i++) { + if (test_thr[i].alive) { + erl_drv_mutex_lock(mtx); + die = 1; + erl_drv_cond_broadcast(cnd); + erl_drv_mutex_unlock(mtx); + erl_drv_thread_join(test_thr[i].tid, NULL); + } + } + + if (mtx) + erl_drv_mutex_destroy(mtx); + if (cnd) + erl_drv_cond_destroy(cnd); + if (rwlck) + erl_drv_rwlock_destroy(rwlck); +} diff --git a/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c b/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c new file mode 100644 index 0000000000..1e98844838 --- /dev/null +++ b/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c @@ -0,0 +1,260 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <setjmp.h> +#include <string.h> + +#ifdef __WIN32__ +#undef HAVE_VSNPRINTF +#define HAVE_VSNPRINTF 1 +#define vsnprintf _vsnprintf +#endif + +#ifndef HAVE_VSNPRINTF +#define HAVE_VSNPRINTF 0 +#endif + +#define COMMENT_BUF_SZ 4096 + +#define TESTCASE_FAILED 0 +#define TESTCASE_SKIPPED 1 +#define TESTCASE_SUCCEEDED 2 + +typedef struct { + TestCaseState_t visible; + ErlDrvPort port; + int result; + jmp_buf done_jmp_buf; + char *comment; + char comment_buf[COMMENT_BUF_SZ]; +} InternalTestCaseState_t; + +ErlDrvData testcase_drv_start(ErlDrvPort port, char *command); +void testcase_drv_stop(ErlDrvData drv_data); +void testcase_drv_run(ErlDrvData drv_data, char *buf, int len); + +static ErlDrvEntry testcase_drv_entry = { + NULL, + testcase_drv_start, + testcase_drv_stop, + testcase_drv_run +}; + + +DRIVER_INIT(testcase_drv) +{ + testcase_drv_entry.driver_name = testcase_name(); + return &testcase_drv_entry; +} + +ErlDrvData +testcase_drv_start(ErlDrvPort port, char *command) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) + driver_alloc(sizeof(InternalTestCaseState_t)); + if (!itcs) { + return ERL_DRV_ERROR_GENERAL; + } + + itcs->visible.testcase_name = testcase_name(); + itcs->visible.extra = NULL; + itcs->port = port; + itcs->result = TESTCASE_FAILED; + itcs->comment = ""; + + return (ErlDrvData) itcs; +} + +void +testcase_drv_stop(ErlDrvData drv_data) +{ + testcase_cleanup((TestCaseState_t *) drv_data); + driver_free((void *) drv_data); +} + +void +testcase_drv_run(ErlDrvData drv_data, char *buf, int len) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) drv_data; + ErlDrvTermData result_atom; + ErlDrvTermData msg[12]; + + itcs->visible.command = buf; + itcs->visible.command_len = len; + + if (setjmp(itcs->done_jmp_buf) == 0) { + testcase_run((TestCaseState_t *) itcs); + itcs->result = TESTCASE_SUCCEEDED; + } + + switch (itcs->result) { + case TESTCASE_SUCCEEDED: + result_atom = driver_mk_atom("succeeded"); + break; + case TESTCASE_SKIPPED: + result_atom = driver_mk_atom("skipped"); + break; + case TESTCASE_FAILED: + default: + result_atom = driver_mk_atom("failed"); + break; + } + + msg[0] = ERL_DRV_ATOM; + msg[1] = (ErlDrvTermData) result_atom; + + msg[2] = ERL_DRV_PORT; + msg[3] = driver_mk_port(itcs->port); + + msg[4] = ERL_DRV_ATOM; + msg[5] = driver_mk_atom(itcs->visible.testcase_name); + + msg[6] = ERL_DRV_STRING; + msg[7] = (ErlDrvTermData) itcs->comment; + msg[8] = (ErlDrvTermData) strlen(itcs->comment); + + msg[9] = ERL_DRV_TUPLE; + msg[10] = (ErlDrvTermData) 4; + + driver_output_term(itcs->port, msg, 11); +} + +int +testcase_assertion_failed(TestCaseState_t *tcs, + char *file, int line, char *assertion) +{ + testcase_failed(tcs, "%s:%d: Assertion failed: \"%s\"", + file, line, assertion); + return 0; +} + +void +testcase_printf(TestCaseState_t *tcs, char *frmt, ...) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; + ErlDrvTermData msg[12]; + va_list va; + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); +#else + vsprintf(itcs->comment_buf, frmt, va); +#endif + va_end(va); + + msg[0] = ERL_DRV_ATOM; + msg[1] = (ErlDrvTermData) driver_mk_atom("print"); + + msg[2] = ERL_DRV_PORT; + msg[3] = driver_mk_port(itcs->port); + + msg[4] = ERL_DRV_ATOM; + msg[5] = driver_mk_atom(itcs->visible.testcase_name); + + msg[6] = ERL_DRV_STRING; + msg[7] = (ErlDrvTermData) itcs->comment_buf; + msg[8] = (ErlDrvTermData) strlen(itcs->comment_buf); + + msg[9] = ERL_DRV_TUPLE; + msg[10] = (ErlDrvTermData) 4; + + driver_output_term(itcs->port, msg, 11); +} + + +void testcase_succeeded(TestCaseState_t *tcs, char *frmt, ...) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; + va_list va; + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); +#else + vsprintf(itcs->comment_buf, frmt, va); +#endif + va_end(va); + + itcs->result = TESTCASE_SUCCEEDED; + itcs->comment = itcs->comment_buf; + + longjmp(itcs->done_jmp_buf, 1); +} + +void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; + va_list va; + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); +#else + vsprintf(itcs->comment_buf, frmt, va); +#endif + va_end(va); + + itcs->result = TESTCASE_SKIPPED; + itcs->comment = itcs->comment_buf; + + longjmp(itcs->done_jmp_buf, 1); +} + +void testcase_failed(TestCaseState_t *tcs, char *frmt, ...) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; + char buf[10]; + size_t bufsz = sizeof(buf); + va_list va; + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); +#else + vsprintf(itcs->comment_buf, frmt, va); +#endif + va_end(va); + + itcs->result = TESTCASE_FAILED; + itcs->comment = itcs->comment_buf; + + if (erl_drv_getenv("ERL_ABORT_ON_FAILURE", buf, &bufsz) == 0 + && strcmp("true", buf) == 0) { + fprintf(stderr, "Testcase \"%s\" failed: %s\n", + itcs->visible.testcase_name, itcs->comment); + abort(); + } + + longjmp(itcs->done_jmp_buf, 1); +} + +void *testcase_alloc(size_t size) +{ + return driver_alloc(size); +} + +void *testcase_realloc(void *ptr, size_t size) +{ + return driver_realloc(ptr, size); +} + +void testcase_free(void *ptr) +{ + driver_free(ptr); +} diff --git a/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.h b/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.h new file mode 100644 index 0000000000..18d5229780 --- /dev/null +++ b/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.h @@ -0,0 +1,58 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#ifndef TESTCASE_DRIVER_H__ +#define TESTCASE_DRIVER_H__ + +#include "erl_driver.h" +#include <stdlib.h> + +typedef struct { + char *testcase_name; + char *command; + int command_len; + void *extra; +} TestCaseState_t; + +#define ASSERT_CLNUP(TCS, B, CLN) \ +do { \ + if (!(B)) { \ + CLN; \ + testcase_assertion_failed((TCS), __FILE__, __LINE__, #B); \ + } \ +} while (0) + +#define ASSERT(TCS, B) ASSERT_CLNUP(TCS, B, (void) 0) + + +void testcase_printf(TestCaseState_t *tcs, char *frmt, ...); +void testcase_succeeded(TestCaseState_t *tcs, char *frmt, ...); +void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...); +void testcase_failed(TestCaseState_t *tcs, char *frmt, ...); +int testcase_assertion_failed(TestCaseState_t *tcs, char *file, int line, + char *assertion); +void *testcase_alloc(size_t size); +void *testcase_realloc(void *ptr, size_t size); +void testcase_free(void *ptr); + + +char *testcase_name(void); +void testcase_run(TestCaseState_t *tcs); +void testcase_cleanup(TestCaseState_t *tcs); + +#endif diff --git a/erts/emulator/test/erl_drv_thread_SUITE_data/tsd.c b/erts/emulator/test/erl_drv_thread_SUITE_data/tsd.c new file mode 100644 index 0000000000..3809c915e0 --- /dev/null +++ b/erts/emulator/test/erl_drv_thread_SUITE_data/tsd.c @@ -0,0 +1,173 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" +#include <stdio.h> + +#define NO_OF_THREADS 17 +#define NO_OF_KEYS 4711 + +struct { + int alive; + ErlDrvTid tid; +} test_thr[NO_OF_THREADS] = {0}; + +struct { + int used; + ErlDrvTSDKey key; +} test_key[NO_OF_KEYS] = {0}; + +typedef struct { + int n; +} thr_arg_t; + +static void *tf(void *vta) +{ + int i; + int thr_val = (((thr_arg_t *) vta)->n << 16); + + for (i = 0; i < NO_OF_KEYS; i++) + erl_drv_tsd_set(test_key[i].key, (void *) (thr_val | i)); + + for (i = 0; i < NO_OF_KEYS; i++) + if (erl_drv_tsd_get(test_key[i].key) != ((void *) (thr_val | i))) + return (void *) 1; + + for (i = 0; i < NO_OF_KEYS; i++) + erl_drv_tsd_set(test_key[i].key, NULL); + + for (i = 0; i < NO_OF_KEYS; i++) + if (erl_drv_tsd_get(test_key[i].key) != NULL) + return (void *) 2; + + return (void *) 3; +} + +void +thr_key_clnup(void) +{ + int i; + for (i = 0; i < NO_OF_KEYS; i++) + erl_drv_tsd_set(test_key[i].key, NULL); +} + +void +testcase_run(TestCaseState_t *tcs) +{ + int i, r; + thr_arg_t ta[NO_OF_THREADS]; + ErlDrvSysInfo sinfo; + + testcase_printf(tcs, "Initializing\n"); + + driver_system_info(&sinfo, sizeof(ErlDrvSysInfo)); + + for (i = 0; i < NO_OF_KEYS; i++) { + char name[100]; + sprintf(name, "key %d", i); + r = erl_drv_tsd_key_create(name, &test_key[i].key); + ASSERT(tcs, r == 0); + test_key[i].used = 1; + } + + for (i = 0; i < NO_OF_KEYS; i++) + erl_drv_tsd_set(test_key[i].key, + (void *) (((NO_OF_THREADS+1) << 16) | i)); + + if (!sinfo.thread_support) + testcase_printf(tcs, "No thread support; testing tsd in one thread\n"); + else { + testcase_printf(tcs, "Creating %d threads\n", NO_OF_THREADS); + + /* Create the threads */ + for (i = 0; i < NO_OF_THREADS; i++) { + char name[100]; + ta[i].n = 0; + sprintf(name, "thread %d", i); + r = erl_drv_thread_create(name, + &test_thr[i].tid, + tf, + (void *) &ta[i], + NULL); + ASSERT_CLNUP(tcs, r == 0, thr_key_clnup()); + test_thr[i].alive = 1; + } + } + + testcase_printf(tcs, "Testing tsd\n"); + + for (i = 0; i < NO_OF_KEYS; i++) + ASSERT_CLNUP(tcs, + ((void *) (((NO_OF_THREADS+1) << 16) | i) + == erl_drv_tsd_get(test_key[i].key)), + thr_key_clnup()); + + testcase_printf(tcs, "Joining threads\n"); + + if (sinfo.thread_support) { + /* Join the threads */ + for (i = 0; i < NO_OF_THREADS; i++) { + void *res; + r = erl_drv_thread_join(test_thr[i].tid, &res); + test_thr[i].alive = 0; + ASSERT_CLNUP(tcs, r == 0, thr_key_clnup()); + ASSERT_CLNUP(tcs, res == ((void *) 3), thr_key_clnup()); + } + } + + thr_key_clnup(); + + for (i = 0; i < NO_OF_KEYS; i++) + ASSERT(tcs, NULL == erl_drv_tsd_get(test_key[i].key)); + + testcase_printf(tcs, "Destroying keys\n"); + + for (i = 0; i < NO_OF_KEYS; i++) + if (test_key[i].used) { + test_key[i].used = 0; + erl_drv_tsd_key_destroy(test_key[i].key); + } + + testcase_printf(tcs, "done\n"); + + if (!sinfo.thread_support) + testcase_succeeded(tcs, "No thread support; only one thread tested"); +} + +char * +testcase_name(void) +{ + return "tsd"; +} + +void +testcase_cleanup(TestCaseState_t *tcs) +{ + int i; + for (i = 0; i < NO_OF_THREADS; i++) + if (test_thr[i].alive) { + test_thr[i].alive = 0; + erl_drv_thread_join(test_thr[i].tid, NULL); + } + + for (i = 0; i < NO_OF_KEYS; i++) + if (test_key[i].used) { + test_key[i].used = 0; + erl_drv_tsd_key_destroy(test_key[i].key); + } +} diff --git a/erts/emulator/test/erl_link_SUITE.erl b/erts/emulator/test/erl_link_SUITE.erl new file mode 100644 index 0000000000..542c8dffbe --- /dev/null +++ b/erts/emulator/test/erl_link_SUITE.erl @@ -0,0 +1,1133 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%%---------------------------------------------------------------------- +%%% File : erl_link_SUITE.erl +%%% Author : Rickard Green <[email protected]> +%%% Purpose : Test erlang links +%%% Created : 13 Dec 2001 by Rickard Green <[email protected]> +%%%---------------------------------------------------------------------- + +-module(erl_link_SUITE). +-author('[email protected]'). + +%-define(line_trace, 1). +-include("test_server.hrl"). + +-export([all/1]). + +% Test cases +-export([links/1, + dist_links/1, + monitor_nodes/1, + process_monitors/1, + dist_process_monitors/1, + busy_dist_port_monitor/1, + busy_dist_port_link/1, + otp_5772_link/1, + otp_5772_dist_link/1, + otp_5772_monitor/1, + otp_5772_dist_monitor/1, + otp_7946/1]). + +-export([init_per_testcase/2, fin_per_testcase/2, end_per_suite/1]). + +% Internal exports +-export([test_proc/0]). + + +-define(LINK_UNDEF, 0). +-define(LINK_PID, 1). +-define(LINK_NODE, 3). + + +% These are to be kept in sync with erl_monitors.h +-define(MON_ORIGIN, 1). +-define(MON_TARGET, 3). + + +-record(erl_link, {type = ?LINK_UNDEF, + pid = [], + targets = []}). + +% This is to be kept in sync with erl_bif_info.c (make_monitor_list) + +-record(erl_monitor, { + type, % MON_ORIGIN or MON_TARGET (1 or 3) + ref, + pid, % Process or nodename + name = [] % registered name or [] + }). + + + +all(suite) -> [links, dist_links, monitor_nodes, process_monitors, + dist_process_monitors, busy_dist_port_monitor, + busy_dist_port_link, otp_5772_link, otp_5772_dist_link, + otp_5772_monitor, otp_5772_dist_monitor, + otp_7946]. + +links(doc) -> ["Tests node local links"]; +links(suite) -> []; +links(Config) when is_list(Config) -> + ?line common_link_test(node(), node()), + ?line true = link(self()), + ?line [] = find_erl_link(self(), ?LINK_PID, self()), + ?line true = unlink(self()), + ?line ok. + +dist_links(doc) -> ["Tests distributed links"]; +dist_links(suite) -> []; +dist_links(Config) when is_list(Config) -> + ?line [NodeName] = get_names(1, dist_link), + ?line {ok, Node} = start_node(NodeName), + ?line common_link_test(node(), Node), + ?line TP4 = spawn(?MODULE, test_proc, []), + ?line TP5 = spawn(?MODULE, test_proc, []), + ?line TP6 = spawn(Node, ?MODULE, test_proc, []), + ?line true = tp_call(TP6, fun() -> link(TP4) end), + ?line check_link(TP4, TP6), + ?line true = tp_call(TP5, + fun() -> + process_flag(trap_exit,true), + link(TP6) + end), + ?line check_link(TP5, TP6), + ?line rpc:cast(Node, erlang, halt, []), + ?line wait_until(fun () -> ?line is_proc_dead(TP4) end), + ?line check_unlink(TP4, TP6), + ?line true = tp_call(TP5, + fun() -> + receive + {'EXIT', TP6, noconnection} -> + true + end + end), + ?line check_unlink(TP5, TP6), + ?line tp_cast(TP5, fun() -> exit(normal) end), + ?line ok. + +common_link_test(NodeA, NodeB) -> + ?line TP1 = spawn(NodeA, ?MODULE, test_proc, []), + ?line check_unlink(TP1, self()), + ?line TP2 = tp_call(TP1, + fun () -> + spawn_link(NodeB, ?MODULE, test_proc, []) + end), + ?line check_link(TP1, TP2), + ?line true = tp_call(TP2, fun() -> unlink(TP1) end), + ?line check_unlink(TP1, TP2), + ?line true = tp_call(TP2, fun() -> link(TP1) end), + ?line check_link(TP1, TP2), + ?line false = tp_call(TP2, fun() -> process_flag(trap_exit, true) end), + ?line tp_cast(TP1, fun () -> exit(died) end), + ?line true = tp_call(TP2, fun() -> + receive + {'EXIT', TP1, died} -> + true + end + end), + ?line check_unlink(TP1, TP2), + ?line TP3 = tp_call(TP2, + fun () -> + spawn_link(NodeA, ?MODULE, test_proc, []) + end), + ?line check_link(TP3, TP2), + ?line tp_cast(TP2, fun() -> exit(died) end), + ?line wait_until(fun () -> ?line is_proc_dead(TP3) end), + ?line check_unlink(TP3, TP2), + ?line ok. + +monitor_nodes(doc) -> ["Tests monitor of nodes"]; +monitor_nodes(suite) -> []; +monitor_nodes(Config) when is_list(Config) -> + ?line [An, Bn, Cn, Dn] = get_names(4, dist_link), + ?line {ok, A} = start_node(An), + ?line {ok, B} = start_node(Bn), + ?line C = list_to_atom(lists:concat([Cn, "@", hostname()])), + ?line D = list_to_atom(lists:concat([Dn, "@", hostname()])), + ?line 0 = no_of_monitor_node(self(), A), + ?line 0 = no_of_monitor_node(self(), B), + ?line monitor_node(A, true), + ?line monitor_node(B, true), + ?line monitor_node(D, true), + ?line monitor_node(D, true), + + %% Has been known to crash the emulator. + ?line {memory,_} = process_info(self(), memory), + + ?line monitor_node(A, false), + ?line monitor_node(B, true), + ?line monitor_node(C, true), + ?line monitor_node(C, false), + ?line monitor_node(C, true), + ?line monitor_node(B, true), + ?line monitor_node(A, false), + ?line monitor_node(B, true), + ?line monitor_node(B, false), + ?line monitor_node(A, true), + ?line check_monitor_node(self(), A, 1), + ?line check_monitor_node(self(), B, 3), + ?line check_monitor_node(self(), C, 0), + ?line check_monitor_node(self(), D, 0), + ?line receive {nodedown, C} -> ok end, + ?line receive {nodedown, C} -> ok end, + ?line receive {nodedown, C} -> ok end, + ?line receive {nodedown, D} -> ok end, + ?line receive {nodedown, D} -> ok end, + ?line stop_node(A), + ?line receive {nodedown, A} -> ok end, + ?line check_monitor_node(self(), A, 0), + ?line check_monitor_node(self(), B, 3), + ?line stop_node(B), + ?line receive {nodedown, B} -> ok end, + ?line receive {nodedown, B} -> ok end, + ?line receive {nodedown, B} -> ok end, + ?line check_monitor_node(self(), B, 0), + ?line receive + {nodedown, X} -> + ?line ?t:fail({unexpected_nodedown, X}) + after 0 -> + ?line ok + end, + ?line ok. + + +process_monitors(doc) -> ["Tests node local process monitors"]; +process_monitors(suite) -> []; +process_monitors(Config) when is_list(Config) -> + ?line common_process_monitors(node(), node()), + ?line Mon1 = erlang:monitor(process,self()), + ?line [] = find_erl_monitor(self(), Mon1), + ?line [Name] = get_names(1, process_monitors), + ?line true = register(Name, self()), + ?line Mon2 = erlang:monitor(process, Name), + ?line [] = find_erl_monitor(self(), Mon2), + ?line receive + {'DOWN', Mon1, _, _, _} = Msg -> + ?line ?t:fail({unexpected_down_msg, Msg}); + {'DOWN', Mon2, _, _, _} = Msg -> + ?line ?t:fail({unexpected_down_msg, Msg}) + after 500 -> + ?line true = erlang:demonitor(Mon1), + ?line true = erlang:demonitor(Mon2), + ?line ok + end. + +dist_process_monitors(doc) -> ["Tests distributed process monitors"]; +dist_process_monitors(suite) -> []; +dist_process_monitors(Config) when is_list(Config) -> + ?line [Name] = get_names(1,dist_process_monitors), + ?line {ok, Node} = start_node(Name), + ?line common_process_monitors(node(), Node), + ?line TP1 = spawn(Node, ?MODULE, test_proc, []), + ?line R1 = erlang:monitor(process, TP1), + ?line TP1O = get_down_object(TP1, self()), + ?line check_process_monitor(self(), TP1, R1), + ?line tp_cast(TP1, fun () -> halt() end), + ?line receive + {'DOWN',R1,process,TP1O,noconnection} -> + ?line ok + end, + ?line check_process_demonitor(self(), TP1, R1), + ?line R2 = erlang:monitor(process, TP1), + ?line receive + {'DOWN',R2,process,TP1O,noconnection} -> + ?line ok + end, + ?line check_process_demonitor(self(), TP1, R2), + ?line ok. + + +common_process_monitors(NodeA, NodeB) -> + ?line TP1 = spawn(NodeA, ?MODULE, test_proc, []), + ?line TP2 = spawn(NodeB, ?MODULE, test_proc, []), + ?line run_common_process_monitors(TP1, TP2), + ?line TP3 = spawn(NodeA, ?MODULE, test_proc, []), + ?line TP4 = spawn(NodeB, ?MODULE, test_proc, []), + ?line [TP4N] = get_names(1, common_process_monitors), + ?line true = tp_call(TP4, fun () -> register(TP4N,self()) end), + ?line run_common_process_monitors(TP3, + case node() == node(TP4) of + true -> TP4N; + false -> {TP4N, node(TP4)} + end), + ?line ok. + +run_common_process_monitors(TP1, TP2) -> + ?line R1 = tp_call(TP1, fun () -> erlang:monitor(process, TP2) end), + ?line check_process_monitor(TP1, TP2, R1), + + ?line tp_call(TP2, fun () -> catch erlang:demonitor(R1) end), + ?line check_process_monitor(TP1, TP2, R1), + + ?line true = tp_call(TP1, fun () -> erlang:demonitor(R1) end), + ?line check_process_demonitor(TP1, TP2, R1), + + ?line R2 = tp_call(TP1, fun () -> erlang:monitor(process, TP2) end), + ?line TP2O = get_down_object(TP2, TP1), + ?line check_process_monitor(TP1, TP2, R2), + ?line tp_cast(TP2, fun () -> exit(bye) end), + ?line wait_until(fun () -> ?line is_proc_dead(TP2) end), + ?line ok = tp_call(TP1, fun () -> + ?line receive + {'DOWN',R2,process,TP2O,bye} -> + ?line ok + end + end), + ?line check_process_demonitor(TP1, TP2, R2), + + ?line R3 = tp_call(TP1, fun () -> erlang:monitor(process, TP2) end), + ?line ok = tp_call(TP1, fun () -> + ?line receive + {'DOWN',R3,process,TP2O,noproc} -> + ?line ok + end + end), + ?line check_process_demonitor(TP1, TP2, R3), + + ?line tp_cast(TP1, fun () -> exit(normal) end), + ?line wait_until(fun () -> ?line is_proc_dead(TP1) end), + ?line ok. + + +busy_dist_port_monitor(doc) -> ["Tests distributed monitor/2, demonitor/1, " + "and 'DOWN' message over busy distribution " + "port"]; +busy_dist_port_monitor(suite) -> []; +busy_dist_port_monitor(Config) when is_list(Config) -> + + ?line Tracer = case os:getenv("TRACE_BUSY_DIST_PORT") of + "true" -> start_busy_dist_port_tracer(); + _ -> false + end, + + ?line [An] = get_names(1, busy_dist_port_monitor), + ?line {ok, A} = start_node(An), + ?line TP1 = spawn(A, ?MODULE, test_proc, []), + %% Check monitor over busy port + ?line M1 = suspend_on_busy_test(A, + "erlang:monitor(process, TP1)", + fun () -> erlang:monitor(process, TP1) end), + ?line check_process_monitor(self(), TP1, M1), + %% Check demonitor over busy port + ?line suspend_on_busy_test(A, + "erlang:demonitor(M1)", + fun () -> erlang:demonitor(M1) end), + ?line check_process_demonitor(self(), TP1, M1), + %% Check down message over busy port + ?line TP2 = spawn(?MODULE, test_proc, []), + ?line M2 = tp_call(TP1, fun () -> erlang:monitor(process, TP2) end), + ?line check_process_monitor(TP1, TP2, M2), + ?line Ref = make_ref(), + ?line Busy = make_busy(A, 1000), + ?line receive after 100 -> ok end, + ?line tp_cast(TP2, fun () -> exit(Ref) end), + ?line receive after 100 -> ok end, + ?line unmake_busy(Busy), + ?line Ref = tp_call(TP1, fun () -> + receive + {'DOWN', M2, process, TP2, Ref} -> + Ref + end + end), + ?line tp_cast(TP1, fun () -> exit(normal) end), + ?line stop_node(A), + ?line stop_busy_dist_port_tracer(Tracer), + ?line ok. + +busy_dist_port_link(doc) -> ["Tests distributed link/1, unlink/1, and 'EXIT'", + " message over busy distribution port"]; +busy_dist_port_link(suite) -> []; +busy_dist_port_link(Config) when is_list(Config) -> + ?line Tracer = case os:getenv("TRACE_BUSY_DIST_PORT") of + "true" -> start_busy_dist_port_tracer(); + _ -> false + end, + + ?line [An] = get_names(1, busy_dist_port_link), + ?line {ok, A} = start_node(An), + ?line TP1 = spawn(A, ?MODULE, test_proc, []), + %% Check link over busy port + ?line suspend_on_busy_test(A, + "link(TP1)", + fun () -> link(TP1) end), + ?line check_link(self(), TP1), + %% Check unlink over busy port + ?line suspend_on_busy_test(A, + "unlink(TP1)", + fun () -> unlink(TP1) end), + ?line check_unlink(self(), TP1), + %% Check trap exit message over busy port + ?line TP2 = spawn(?MODULE, test_proc, []), + ?line ok = tp_call(TP1, fun () -> + process_flag(trap_exit, true), + link(TP2), + ok + end), + ?line check_link(TP1, TP2), + ?line Ref = make_ref(), + ?line Busy = make_busy(A, 1000), + ?line receive after 100 -> ok end, + ?line tp_cast(TP2, fun () -> exit(Ref) end), + ?line receive after 100 -> ok end, + ?line unmake_busy(Busy), + ?line Ref = tp_call(TP1, fun () -> + receive + {'EXIT', TP2, Ref} -> + Ref + end + end), + ?line tp_cast(TP1, fun () -> exit(normal) end), + ?line stop_node(A), + ?line stop_busy_dist_port_tracer(Tracer), + ?line ok. + + +otp_5772_link(doc) -> []; +otp_5772_link(suite) -> []; +otp_5772_link(Config) when is_list(Config) -> + ?line otp_5772_link_test(node()). + +otp_5772_dist_link(doc) -> []; +otp_5772_dist_link(suite) -> []; +otp_5772_dist_link(Config) when is_list(Config) -> + ?line [An] = get_names(1, otp_5772_dist_link), + ?line {ok, A} = start_node(An), + ?line otp_5772_link_test(A), + ?line stop_node(A). + +otp_5772_link_test(Node) -> + ?line Prio = process_flag(priority, high), + ?line TE = process_flag(trap_exit, true), + ?line TP1 = spawn_opt(Node, ?MODULE, test_proc, [], + [link, {priority, low}]), + exit(TP1, bang), + unlink(TP1), + ?line receive + {'EXIT', TP1, _} -> + ?line ok + after 0 -> + ?line ok + end, + ?line receive + {'EXIT', TP1, _} = Exit -> + ?line ?t:fail({got_late_exit_message, Exit}) + after 1000 -> + ?line ok + end, + ?line process_flag(trap_exit, TE), + ?line process_flag(priority, Prio), + ?line ok. + +otp_5772_monitor(doc) -> []; +otp_5772_monitor(suite) -> []; +otp_5772_monitor(Config) when is_list(Config) -> + ?line otp_5772_monitor_test(node()). + +otp_5772_dist_monitor(doc) -> []; +otp_5772_dist_monitor(suite) -> []; +otp_5772_dist_monitor(Config) when is_list(Config) -> + ?line [An] = get_names(1, otp_5772_dist_monitor), + ?line {ok, A} = start_node(An), + ?line otp_5772_monitor_test(A), + ?line stop_node(A), + ?line ok. + +otp_5772_monitor_test(Node) -> + ?line Prio = process_flag(priority, high), + ?line TP1 = spawn_opt(Node, ?MODULE, test_proc, [], [{priority, low}]), + ?line M1 = erlang:monitor(process, TP1), + ?line exit(TP1, bang), + ?line erlang:demonitor(M1), + ?line receive + {'DOWN', M1, _, _, _} -> + ?line ok + after 0 -> + ?line ok + end, + ?line receive + {'DOWN', M1, _, _, _} = Down -> + ?line ?t:fail({got_late_down_message, Down}) + after 1000 -> + ?line ok + end, + ?line process_flag(priority, Prio), + ?line ok. + +otp_7946(Config) when is_list(Config) -> + ?line [NodeName] = get_names(1, otp_7946), + ?line {ok, Node} = start_node(NodeName), + ?line Proc = rpc:call(Node, erlang, whereis, [net_kernel]), + ?line Mon = erlang:monitor(process, Proc), + ?line rpc:cast(Node, erlang, halt, []), + ?line receive {'DOWN', Mon, process, Proc , _} -> ok end, + ?line {Linker, LMon} = spawn_monitor(fun () -> + link(Proc), + receive + after infinity -> ok + end + end), + ?line receive + {'DOWN', LMon, process, Linker, Reason} -> + ?line ?t:format("Reason=~p~n", [Reason]), + ?line Reason = noconnection + end. + +%% +%% -- Internal utils -------------------------------------------------------- +%% + +-define(BUSY_DATA_KEY, '__busy__port__data__'). +-define(BUSY_DATA_SIZE, 1024*1024). + +busy_data() -> + case get(?BUSY_DATA_KEY) of + undefined -> + set_busy_data([]); + Data -> + true = is_binary(Data), + true = size(Data) == ?BUSY_DATA_SIZE, + Data + end. + +set_busy_data(SetData) -> + case get(?BUSY_DATA_KEY) of + undefined -> + Data = case SetData of + D when is_binary(D), size(D) == ?BUSY_DATA_SIZE -> + SetData; + _ -> + list_to_binary(lists:duplicate(?BUSY_DATA_SIZE, 253)) + end, + put(?BUSY_DATA_KEY, Data), + Data; + OldData -> + OldData + end. + +freeze_node(Node, MS) -> + Own = 500, + DoingIt = make_ref(), + Freezer = self(), + spawn_link(Node, + fun () -> + erts_debug:set_internal_state(available_internal_state, + true), + dport_send(Freezer, DoingIt), + receive after Own -> ok end, + erts_debug:set_internal_state(block, MS+Own) + end), + receive DoingIt -> ok end, + receive after Own -> ok end. + +make_busy(Node, Time) when is_integer(Time) -> + Own = 500, + freeze_node(Node, Time+Own), + Data = busy_data(), + %% first make port busy + Pid = spawn_link(fun () -> + forever(fun () -> + dport_reg_send(Node, + '__noone__', + Data) + end) + end), + receive after Own -> ok end, + wait_until(fun () -> + case process_info(Pid, status) of + {status, suspended} -> true; + _ -> false + end + end), + %% then dist entry + make_busy(Node, [nosuspend], Data), + Pid. + +make_busy(Node, Opts, Data) -> + case erlang:send({'__noone__', Node}, Data, Opts) of + nosuspend -> nosuspend; + _ -> make_busy(Node, Opts, Data) + end. + +unmake_busy(Pid) -> + unlink(Pid), + exit(Pid, bang). + +suspend_on_busy_test(Node, Doing, Fun) -> + Tester = self(), + DoIt = make_ref(), + Done = make_ref(), + Data = busy_data(), + spawn_link(fun () -> + set_busy_data(Data), + Busy = make_busy(Node, 1000), + Tester ! DoIt, + receive after 100 -> ok end, + Info = process_info(Tester, [status, current_function]), + unmake_busy(Busy), + ?t:format("~p doing ~s: ~p~n", [Tester, Doing, Info]), + Tester ! {Done, Info} + end), + receive DoIt -> ok end, + Res = Fun(), + receive + {Done, MyInfo} -> + %% Don't match arity; it is different in + %% debug and optimized emulator + [{status, suspended}, + {current_function, {erlang, bif_return_trap, _}}] = MyInfo, + ok + end, + Res. + +% get_node(Name) when is_atom(Name) -> +% ?line node(); +% get_node({Name, Node}) when is_atom(Name) -> +% ?line Node; +% get_node(NC) when is_pid(NC); is_port(NC); is_reference(NC) -> +% ?line node(NC). + +get_down_object(Item, _) when is_pid(Item) -> + Item; +get_down_object({Name, Node} = Item, _) when is_atom(Name); is_atom(Node) -> + Item; +get_down_object(Item, Watcher) when is_atom(Item), is_pid(Watcher) -> + {Item, node(Watcher)}; +get_down_object(Item, {_,Node}) when is_atom(Item), is_atom(Node) -> + {Item, Node}; +get_down_object(Item, Watcher) when is_atom(Item), is_atom(Watcher) -> + {Item, node()}. + +is_proc_dead(P) -> + case is_proc_alive(P) of + true -> false; + false -> true + end. + +is_proc_alive(Pid) when is_pid(Pid), node(Pid) == node() -> + ?line is_process_alive(Pid); +is_proc_alive(Name) when is_atom(Name) -> + ?line case catch whereis(Name) of + Pid when is_pid(Pid) -> + ?line is_proc_alive(Pid); + _ -> + ?line false + end; +is_proc_alive({Name, Node}) when is_atom(Name), Node == node() -> + ?line is_proc_alive(Name); +is_proc_alive(Proc) -> + ?line is_remote_proc_alive(Proc). + +is_remote_proc_alive({Name, Node}) when is_atom(Name), is_atom(Node) -> + ?line is_remote_proc_alive(Name, Node); +is_remote_proc_alive(Pid) when is_pid(Pid) -> + ?line is_remote_proc_alive(Pid, node(Pid)); +is_remote_proc_alive(_) -> + ?line false. + +is_remote_proc_alive(PN, Node) -> + ?line S = self(), + ?line R = make_ref(), + ?line monitor_node(Node, true), + ?line _P = spawn(Node, fun () -> S ! {R, is_proc_alive(PN)} end), + ?line receive + {R, Bool} -> + ?line monitor_node(Node, false), + ?line Bool; + {nodedown, Node} -> + ?line false + end. + +wait_until(Fun) -> + ?line case Fun() of + true -> + ?line ok; + _ -> + ?line receive + after 100 -> + ?line wait_until(Fun) + end + end. + +forever(Fun) -> + Fun(), + forever(Fun). + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + ?line Dog = ?t:timetrap(?t:minutes(1)), + case catch erts_debug:get_internal_state(available_internal_state) of + true -> ok; + _ -> erts_debug:set_internal_state(available_internal_state, true) + end, + ?line [{watchdog, Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + ?line Dog = ?config(watchdog, Config), + ?line ?t:timetrap_cancel(Dog). + +end_per_suite(_Config) -> + catch erts_debug:set_internal_state(available_internal_state, false). + +tp_call(Tp, Fun) -> + ?line R = make_ref(), + ?line Tp ! {call, self(), R, Fun}, + ?line receive + {R, Res} -> + ?line Res + end. + +tp_cast(Tp, Fun) -> + ?line Tp ! {cast, Fun}. + +test_proc() -> + ?line receive + {call, From, Ref, Fun} -> + ?line From ! {Ref, Fun()}; + {cast, Fun} -> + ?line Fun() + end, + ?line test_proc(). + +expand_link_list([#erl_link{type = ?LINK_NODE, targets = N} = Rec | T]) -> + lists:duplicate(N,Rec#erl_link{targets = []}) ++ expand_link_list(T); +expand_link_list([#erl_link{targets = [#erl_link{pid = Pid}]} = Rec | T]) -> + [Rec#erl_link{targets = [Pid]} | expand_link_list(T)]; +expand_link_list([#erl_link{targets = [#erl_link{pid = Pid}|TT]} = Rec | T]) -> + [ Rec#erl_link{targets = [Pid]} | expand_link_list( + [Rec#erl_link{targets = TT} | T])]; +expand_link_list([#erl_link{targets = []} = Rec | T]) -> + [Rec | expand_link_list(T)]; +expand_link_list([]) -> + []. + +get_local_link_list(Obj) -> + case catch erts_debug:get_internal_state({link_list, Obj}) of + LL when is_list(LL) -> + expand_link_list(LL); + _ -> + [] + end. + +get_remote_link_list(Node, Obj) -> + case catch rpc:call(Node, erts_debug, get_internal_state, + [{link_list, Obj}]) of + LL when is_list(LL) -> + expand_link_list(LL); + _ -> + [] + end. + + +get_link_list({Node, DistEntry}) when Node == node(), is_atom(DistEntry) -> + get_local_link_list(DistEntry); +get_link_list({Node, DistEntry}) when is_atom(Node), is_atom(DistEntry) -> + get_remote_link_list(Node, DistEntry); +get_link_list(P) when is_pid(P); is_port(P) -> + case node(P) of + Node when Node == node() -> + get_local_link_list(P); + Node -> + get_remote_link_list(Node, P) + end; +get_link_list(undefined) -> + []. + +get_local_monitor_list(Obj) -> + case catch erts_debug:get_internal_state({monitor_list, Obj}) of + LL when is_list(LL) -> + LL; + _ -> + [] + end. + +get_remote_monitor_list(Node, Obj) -> + case catch rpc:call(Node, erts_debug, get_internal_state, + [{monitor_list, Obj}]) of + LL when is_list(LL) -> + LL; + _ -> + [] + end. + + +get_monitor_list({Node, DistEntry}) when Node == node(), is_atom(DistEntry) -> + get_local_monitor_list(DistEntry); +get_monitor_list({Node, DistEntry}) when is_atom(Node), is_atom(DistEntry) -> + get_remote_monitor_list(Node, DistEntry); +get_monitor_list(P) when is_pid(P) -> + case node(P) of + Node when Node == node() -> + get_local_monitor_list(P); + Node -> + get_remote_monitor_list(Node, P) + end; +get_monitor_list(undefined) -> + []. + + +find_erl_monitor(Pid, Ref) when is_reference(Ref) -> + lists:foldl(fun (#erl_monitor{ref = R} = EL, Acc) when R == Ref -> + [EL|Acc]; + (_, Acc) -> + Acc + end, + [], + get_monitor_list(Pid)). + +% find_erl_link(Obj, Ref) when is_reference(Ref) -> +% ?line lists:foldl(fun (#erl_link{ref = R} = EL, Acc) when R == Ref -> +% ?line [EL|Acc]; +% (_, Acc) -> +% ?line Acc +% end, +% [], +% get_link_list(Obj)). + +find_erl_link(Obj, Type, [Item, Data]) when is_pid(Item); + is_port(Item); + is_atom(Item) -> + lists:foldl(fun (#erl_link{type = T, pid = I, targets = D} = EL, + Acc) when T == Type, I == Item -> + case Data of + D -> + [EL|Acc]; + [] -> + [EL|Acc]; + _ -> + Acc + end; + (_, Acc) -> + Acc + end, + [], + get_link_list(Obj)); +find_erl_link(Obj, Type, Item) when is_pid(Item); is_port(Item); is_atom(Item) -> + find_erl_link(Obj, Type, [Item, []]). + + + +check_link(A, B) -> + ?line [#erl_link{type = ?LINK_PID, + pid = B, + targets = []}] = find_erl_link(A, ?LINK_PID, B), + ?line [#erl_link{type = ?LINK_PID, + pid = A, + targets = []}] = find_erl_link(B, ?LINK_PID, A), + ?line case node(A) == node(B) of + false -> + ?line [#erl_link{type = ?LINK_PID, + pid = A, + targets = [B]}] = find_erl_link({node(A), + node(B)}, + ?LINK_PID, + [A, [B]]), + ?line [#erl_link{type = ?LINK_PID, + pid = B, + targets = [A]}] = find_erl_link({node(B), + node(A)}, + ?LINK_PID, + [B, [A]]); + true -> + ?line [] = find_erl_link({node(A), node(B)}, + ?LINK_PID, + [A, [B]]), + ?line [] = find_erl_link({node(B), node(A)}, + ?LINK_PID, + [B, [A]]) + end, + ?line ok. + +check_unlink(A, B) -> + ?line [] = find_erl_link(A, ?LINK_PID, B), + ?line [] = find_erl_link(B, ?LINK_PID, A), + ?line [] = find_erl_link({node(A), node(B)}, ?LINK_PID, [A, [B]]), + ?line [] = find_erl_link({node(B), node(A)}, ?LINK_PID, [B, [A]]), + ?line ok. + +check_process_monitor(From, {Name, Node}, Ref) when is_pid(From), + is_atom(Name), + Node == node(From), + is_reference(Ref) -> + ?line check_process_monitor(From, Name, Ref); +check_process_monitor(From, {Name, Node}, Ref) when is_pid(From), + is_atom(Name), + is_atom(Node), + is_reference(Ref) -> + ?line MonitoredPid = rpc:call(Node, erlang, whereis, [Name]), + ?line [#erl_monitor{type = ?MON_ORIGIN, + ref = Ref, + pid = Node, + name = Name}] = find_erl_monitor(From, Ref), + ?line [#erl_monitor{type = ?MON_TARGET, + ref = Ref, + pid = From, + name = Name}] = find_erl_monitor({node(From), Node}, Ref), + ?line [#erl_monitor{type = ?MON_ORIGIN, + ref = Ref, + pid = MonitoredPid, + name = Name}] = find_erl_monitor({Node, node(From)}, Ref), + ?line [#erl_monitor{type = ?MON_TARGET, + ref = Ref, + pid = From, + name = Name}] = find_erl_monitor(MonitoredPid, Ref), + ?line ok; +check_process_monitor(From, Name, Ref) when is_pid(From), + is_atom(Name), + undefined /= Name, + is_reference(Ref) -> + ?line MonitoredPid = rpc:call(node(From), erlang, whereis, [Name]), + + ?line [#erl_monitor{type = ?MON_ORIGIN, + ref = Ref, + pid = MonitoredPid, + name = Name}] = find_erl_monitor(From, Ref), + + + ?line [#erl_monitor{type = ?MON_TARGET, + ref = Ref, + pid = From, + name = Name}] = find_erl_monitor(MonitoredPid,Ref), + ok; +check_process_monitor(From, To, Ref) when is_pid(From), + is_pid(To), + is_reference(Ref) -> + ?line OriMon = [#erl_monitor{type = ?MON_ORIGIN, + ref = Ref, + pid = To}], + + ?line OriMon = find_erl_monitor(From, Ref), + + ?line TargMon = [#erl_monitor{type = ?MON_TARGET, + ref = Ref, + pid = From}], + ?line TargMon = find_erl_monitor(To, Ref), + + + ?line case node(From) == node(To) of + false -> + ?line TargMon = find_erl_monitor({node(From), node(To)}, Ref), + ?line OriMon = find_erl_monitor({node(To), node(From)}, Ref); + true -> + ?line [] = find_erl_monitor({node(From), node(From)}, Ref) + end, + ?line ok. + + +check_process_demonitor(From, {undefined, Node}, Ref) when is_pid(From), + is_reference(Ref) -> + ?line [] = find_erl_monitor(From, Ref), + ?line case node(From) == Node of + false -> + ?line [] = find_erl_monitor({node(From), Node}, Ref), + ?line [] = find_erl_monitor({Node, node(From)}, Ref); + true -> + ?line [] = find_erl_monitor({Node, Node}, Ref) + end, + ?line ok; +check_process_demonitor(From, {Name, Node}, Ref) when is_pid(From), + is_atom(Name), + Node == node(From), + is_reference(Ref) -> + ?line MonitoredPid = rpc:call(Node, erlang, whereis, [Name]), + ?line case rpc:call(Node, erlang, whereis, [Name]) of + undefined -> + ?line check_process_demonitor(From, {undefined, Node}, Ref); + MonitoredPid -> + ?line check_process_demonitor(From, MonitoredPid, Ref) + end; +check_process_demonitor(From, {Name, Node}, Ref) when is_pid(From), + is_atom(Name), + is_atom(Node), + is_reference(Ref) -> + ?line MonitoredPid = rpc:call(Node, erlang, whereis, [Name]), + ?line [] = find_erl_monitor(From, Ref), + ?line [] = find_erl_monitor({node(From), Node}, Ref), + ?line [] = find_erl_monitor({Node, node(From)}, Ref), + ?line [] = find_erl_monitor(MonitoredPid, Ref), + ?line ok; +check_process_demonitor(From, undefined, Ref) when is_pid(From), + is_reference(Ref) -> + ?line [] = find_erl_monitor(From, Ref), + ?line case node(From) == node() of + false -> + ?line [] = find_erl_monitor({node(From), node()}, Ref), + ?line [] = find_erl_monitor({node(), node(From)}, Ref); + true -> + ?line [] = find_erl_monitor({node(), node()}, Ref) + end, + ?line ok; +check_process_demonitor(From, Name, Ref) when is_pid(From), + is_atom(Name), + undefined /= Name, + is_reference(Ref) -> + ?line check_process_demonitor(From, {Name, node()}, Ref); +check_process_demonitor(From, To, Ref) when is_pid(From), + is_pid(To), + is_reference(Ref) -> + ?line [] = find_erl_monitor(From, Ref), + ?line [] = find_erl_monitor(To, Ref), + ?line case node(From) == node(To) of + false -> + ?line [] = find_erl_monitor({node(From), node(To)}, Ref), + ?line [] = find_erl_monitor({node(To), node(From)}, Ref); + true -> + ?line [] = find_erl_monitor({node(From), node(From)}, Ref) + end, + ?line ok. + +no_of_monitor_node(From, Node) when is_pid(From), is_atom(Node) -> + ?line length(find_erl_link(From, ?LINK_NODE, Node)). + +check_monitor_node(From, Node, No) when is_pid(From), + is_atom(Node), + is_integer(No), + No >= 0 -> + ?line LL = lists:duplicate(No, #erl_link{type = ?LINK_NODE, pid = Node}), + ?line DLL = lists:duplicate(No, #erl_link{type = ?LINK_NODE, pid = From}), + ?line LL = find_erl_link(From, ?LINK_NODE, Node), + ?line DLL = find_erl_link({node(From), Node}, ?LINK_NODE, From), + ?line ok. + + + +hostname() -> + ?line from($@, atom_to_list(node())). + +from(H, [H | T]) -> T; +from(H, [_ | T]) -> from(H, T); +from(_H, []) -> []. + +get_names(N, T) when is_atom(T) -> + get_names(N, T, []). +get_names(0, _, Acc) -> + Acc; +get_names(N, T, Acc) -> + {A, B, C} = now(), + get_names(N-1, T, [list_to_atom(atom_to_list(?MODULE) + ++ "-" + ++ atom_to_list(T) + ++ "-" + ++ integer_to_list(A) + ++ "-" + ++ integer_to_list(B) + ++ "-" + ++ integer_to_list(C)) | Acc]). + +start_node(Name) -> + ?line start_node(Name, ""). + +start_node(Name, Args) -> + ?line Pa = filename:dirname(code:which(?MODULE)), + ?line Res = ?t:start_node(Name, slave, [{args, Args ++ " -pa " ++ Pa}]), + ?line {ok, Node} = Res, + ?line rpc:call(Node, erts_debug, set_internal_state, + [available_internal_state, true]), + ?line Res. + + +stop_node(Node) -> + ?line ?t:stop_node(Node). + +-define(COOKIE, ''). +-define(DOP_LINK, 1). +-define(DOP_SEND, 2). +-define(DOP_EXIT, 3). +-define(DOP_UNLINK, 4). +-define(DOP_NODE_LINK, 5). +-define(DOP_REG_SEND, 6). +-define(DOP_GROUP_LEADER, 7). +-define(DOP_EXIT2, 8). + +-define(DOP_SEND_TT, 12). +-define(DOP_EXIT_TT, 13). +-define(DOP_REG_SEND_TT, 16). +-define(DOP_EXIT2_TT, 18). + +-define(DOP_MONITOR_P, 19). +-define(DOP_DEMONITOR_P, 20). +-define(DOP_MONITOR_P_EXIT, 21). + +dport_send(To, Msg) -> + Node = node(To), + DPrt = case dport(Node) of + undefined -> + pong = net_adm:ping(Node), + dport(Node); + Prt -> + Prt + end, + port_command(DPrt, [dmsg_hdr(), + dmsg_ext({?DOP_SEND, + ?COOKIE, + To}), + dmsg_ext(Msg)]). + +dport_reg_send(Node, Name, Msg) -> + DPrt = case dport(Node) of + undefined -> + pong = net_adm:ping(Node), + dport(Node); + Prt -> + Prt + end, + port_command(DPrt, [dmsg_hdr(), + dmsg_ext({?DOP_REG_SEND, + self(), + ?COOKIE, + Name}), + dmsg_ext(Msg)]). + +dport(Node) when is_atom(Node) -> + case catch erts_debug:get_internal_state(available_internal_state) of + true -> true; + _ -> erts_debug:set_internal_state(available_internal_state, true) + end, + erts_debug:get_internal_state({dist_port, Node}). + +dmsg_hdr() -> + [131, % Version Magic + $D, % Dist header + 0]. % No atom cache referenses + +dmsg_ext(Term) -> + <<131, Res/binary>> = term_to_binary(Term), + Res. + +start_busy_dist_port_tracer() -> + Tracer = spawn_link(fun () -> busy_dist_port_tracer() end), + erlang:system_monitor(Tracer, [busy_dist_port]), + Tracer. + +stop_busy_dist_port_tracer(Tracer) when is_pid(Tracer) -> + unlink(Tracer), + exit(Tracer, bye); +stop_busy_dist_port_tracer(_) -> + true. + +busy_dist_port_tracer() -> + receive + {monitor, _SuspendedProcess, busy_dist_port, _Port} = M -> + erlang:display(M), + busy_dist_port_tracer() + end. + + + + diff --git a/erts/emulator/test/erts_debug_SUITE.erl b/erts/emulator/test/erts_debug_SUITE.erl new file mode 100644 index 0000000000..e60a999df1 --- /dev/null +++ b/erts/emulator/test/erts_debug_SUITE.erl @@ -0,0 +1,72 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(erts_debug_SUITE). +-include("test_server.hrl"). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + flat_size/1,flat_size_big/1,df/1]). + +all(suite) -> + [flat_size,flat_size_big,df]. + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog=?t:timetrap(?t:minutes(2)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +flat_size(Config) when is_list(Config) -> + 0 = erts_debug:flat_size([]), + 0 = erts_debug:flat_size(42), + 2 = erts_debug:flat_size([a|b]), + 1 = erts_debug:flat_size({}), + 2 = erts_debug:flat_size({[]}), + 3 = erts_debug:flat_size({a,b}), + 7 = erts_debug:flat_size({a,[b,c]}), + ok. + +flat_size_big(Config) when is_list(Config) -> + %% Build a term whose external size only fits in a big num (on 32-bit CPU). + flat_size_big_1(16#11111111111111117777777777777777888889999, 0, 16#FFFFFFF). + +flat_size_big_1(Term, Size0, Limit) when Size0 < Limit -> + case erts_debug:flat_size(Term) of + Size when is_integer(Size), Size0 < Size -> + io:format("~p", [Size]), + flat_size_big_1([Term|Term], Size, Limit) + end; +flat_size_big_1(_, _, _) -> ok. + +df(Config) when is_list(Config) -> + ?line P0 = pps(), + ?line PrivDir = ?config(priv_dir, Config), + ?line ok = file:set_cwd(PrivDir), + ?line erts_debug:df(?MODULE), + ?line Beam = filename:join(PrivDir, ?MODULE_STRING++".dis"), + ?line {ok,Bin} = file:read_file(Beam), + ?line ok = io:put_chars(binary_to_list(Bin)), + ?line ok = file:delete(Beam), + ?line true = (P0 == pps()), + ok. + +pps() -> + {erlang:ports()}. diff --git a/erts/emulator/test/estone_SUITE.erl b/erts/emulator/test/estone_SUITE.erl new file mode 100644 index 0000000000..7fb92faf0d --- /dev/null +++ b/erts/emulator/test/estone_SUITE.erl @@ -0,0 +1,1107 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(estone_SUITE). +%% Test functions +-export([all/1,estone/1]). +-export([init_per_testcase/2, fin_per_testcase/2]). + +%% Internal exports for EStone tests +-export([lists/1, + msgp/1, + msgp_medium/1, + msgp_huge/1, + pattern/1, + trav/1, + port_io/1, + large_dataset_work/1, + large_local_dataset_work/1,mk_big_procs/1,big_proc/0, + alloc/1, + bif_dispatch/1, + binary_h/1,echo/1, + ets/1, + generic/1,req/2,gserv/4,handle_call/3, + int_arith/1, + float_arith/1, + fcalls/1,remote0/1,remote1/1,app0/1,app1/1, + timer/1, + links/1,lproc/1, + run_micro/3,p1/1,ppp/3,macro/2,micros/0]). + + +-include("test_server.hrl"). + +%% Test suite defines +-define(default_timeout, ?t:minutes(10)). + +%% EStone defines +-define(TOTAL, (3000 * 1000 * 100)). %% 300 secs +-define(BIGPROCS, 2). +-define(BIGPROC_SIZE, 50). +-define(STONEFACTOR, 31000000). %% Factor to make the reference + %% implementation to make 1000 TS_ESTONES. +-record(micro, + {function, %% The name of the function implementing the micro + weight, %% How important is this in typical applications ?? + loops = 100,%% initial data + tt1, %% time to do one round + str}). %% Header string + + + + +init_per_testcase(_Case, Config) -> + ?line Dog=test_server:timetrap(?default_timeout), + [{watchdog, Dog}|Config]. +fin_per_testcase(_Case, Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +all(suite) -> [estone]. + +estone(suite) -> + []; +estone(doc) -> + ["EStone Test"]; +estone(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir,Config), + ?line Mhz=get_cpu_speed(os:type(),DataDir), + ?line L = ?MODULE:macro(?MODULE:micros(),DataDir), + ?line {Total, Stones} = sum_micros(L, 0, 0), + ?line pp(Mhz,Total,Stones,L), + ?line {comment,Mhz ++ " MHz, " ++ + integer_to_list(Stones) ++ " ESTONES"}. + +%% +%% Calculate CPU speed +%% +%% get_cpu_speed() now returns a string. For multiprocessor +%% machines (at least on Solaris) the format is: <F1>+<F2>[+...] +%% +get_cpu_speed({win32, _},_DataDir) -> + RegH = + case catch win32reg:open([read]) of + {ok, Handle} -> + Handle; + _ -> + io:format("Error.~nCannot determine CPU clock" + "frequency.~n" + "Please set the environment variable" + "\"CPU_SPEED\"~n"), + exit(self(), {error, no_cpu_speed}) + end, + case win32reg:change_key(RegH,"\\hkey_local_machine\\hardware\\" + "description\\system\\centralprocessor" + "\\0") of + ok -> + ok; + _ -> + io:format("Error.~nRegistry seems to be damaged or" + "unavailable.~n" + "Please set the environment variable" + "\"CPU_SPEED\",~nor correct your registry" + "if possible.~n"), + win32reg:close(RegH), + exit(self(), {error, no_cpu_speed}) + end, + case win32reg:value(RegH, "~MHZ") of + {ok, Speed} -> + win32reg:close(RegH), + integer_to_list(Speed); + _ -> + io:format("Error.~nRegistry seems to be damaged or " + "unavailable.~n"), + io:format("Please set the environment variable" + "\"CPU_SPEED\"~n"), + win32reg:close(RegH), + exit(self(), {error, no_cpu_speed}) + end; +get_cpu_speed({unix, sunos},DataDir) -> + os:cmd(filename:join(DataDir,"sunspeed.sh")) -- "\n"; +get_cpu_speed(_Other,_DataDir) -> + %% Cannot determine CPU speed + "UNKNOWN". + + +%% +%% Pretty Print EStone Result +%% +pp(Mhz,Total,Stones,Ms) -> + io:format("EStone test completed~n",[]), + io:format("**** CPU speed ~s MHz ****~n",[Mhz]), + io:format("**** Total time ~w seconds ****~n", [Total / 1000000]), + io:format("**** ESTONES = ~w ****~n~n", [Stones]), + io:format("~-31s ~-12s ~-10s % ~-10s ~n~n", + [" Title", "Millis", "Estone", "Loops"]), + erlang:display({'ESTONES', Stones}), + pp2(Ms). + +sum_micros([], Tot, Stones) -> {Tot, Stones}; +sum_micros([H|T], Tot, Sto) -> + sum_micros(T, ks(microsecs, H) + Tot, ks(estones, H) + Sto). + +pp2([]) -> ok; +pp2([R|Tail]) -> + io:format("~-35s ~-12w ~-10w ~-2w ~-10w ~n", + [ks(title,R), + round(ks(microsecs, R) / 1000), + ks(estones, R), + ks(weight_percentage, R), + ks(loops, R)]), + pp2(Tail). + +ks(K, L) -> + {value, {_, V}} = lists:keysearch(K, 1, L), + V. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% EStone test +micro(lists) -> + #micro{function = lists, + weight = 7, + loops = 6400, + str = "list manipulation"}; +micro(msgp) -> + #micro{function = msgp, + weight = 10, + loops = 1515, + str = "small messages"}; +micro(msgp_medium) -> + #micro{function = msgp_medium, + weight = 14, + loops = 1527, + str = "medium messages"}; +micro(msgp_huge) -> + #micro{function = msgp_huge, + weight = 4, + loops = 52, + str = "huge messages"}; + +micro(pattern) -> + #micro{function = pattern, + weight = 5, + loops = 1046, + str = "pattern matching"}; + +micro(trav) -> + #micro{function = trav, + weight = 4, + loops = 2834, + str = "traverse"}; + +micro(port_io) -> + #micro{function = port_io, + weight = 12, + loops = 4800, + str = "Port i/o"}; + +micro(large_dataset_work) -> + #micro{function = large_dataset_work, + weight = 3, + loops = 1193, + str = "Work with large dataset"}; + +micro(large_local_dataset_work) -> + #micro{function = large_local_dataset_work, + weight = 3, + loops = 1174, + str = "Work with large local dataset"}; + +micro(alloc) -> + #micro{function = alloc, + weight = 2, + loops = 3710, + str = "Alloc and dealloc"}; + +micro(bif_dispatch) -> + #micro{function = bif_dispatch, + weight = 5, + loops = 1623, + str = "Bif dispatch"}; + +micro(binary_h) -> + #micro{function = binary_h, + weight = 4, + loops = 581, + str = "Binary handling"}; +micro(ets) -> + #micro{function = ets, + weight = 6, + loops = 342, + str = "ets datadictionary"}; +micro(generic) -> + #micro{function = generic, + weight = 9, + loops = 7977, + str = "Generic server (with timeout)"}; +micro(int_arith) -> + #micro{function = int_arith, + weight = 3, + loops = 4157, + str = "Small Integer arithmetics"}; +micro(float_arith) -> + #micro{function = float_arith, + weight = 1, + loops = 5526, + str = "Float arithmetics"}; +micro(fcalls) -> + #micro{function = fcalls, + weight = 5, + loops = 882, + str = "Function calls"}; + +micro(timer) -> + #micro{function = timer, + weight = 2, + loops = 2312, + str = "Timers"}; + +micro(links) -> + #micro{function = links, + weight = 1, + loops = 30, + str = "Links"}. + + + +%% Return a list of micro's +micros() -> + [ + micro(lists), + micro(msgp), + micro(msgp_medium), + micro(msgp_huge), + micro(pattern), + micro(trav), + micro(port_io), + micro(large_dataset_work), + micro(large_local_dataset_work), + micro(alloc), + micro(bif_dispatch), + micro(binary_h), + micro(ets), + micro(generic), + micro(int_arith), + micro(float_arith), + micro(fcalls), + micro(timer), + micro(links) + ]. + +macro(Ms,DataDir) -> + erlang:now(), %% compensate for old 4.3 firsttime clock bug :-( + statistics(reductions), + statistics(runtime), + lists(500), %% fixup cache on first round + run_micros(Ms,DataDir). + +run_micros([],_) -> + io:nl(), + []; +run_micros([H|T],DataDir) -> + R = run_micro(H,DataDir), + [R| run_micros(T,DataDir)]. + +run_micro(M,DataDir) -> + Pid = spawn(?MODULE, run_micro, [self(),M,DataDir]), + Res = receive {Pid, Reply} -> Reply end, + {value,{title,Title}} = lists:keysearch(title,1,Reply), + {value,{estones,Estones}} = lists:keysearch(estones,1,Reply), + erlang:display({Title,Estones}), + Res. + + +run_micro(Top, M, DataDir) -> + EstoneCat = filename:join(DataDir,"estone_cat"), + put(estone_cat,EstoneCat), + Top ! {self(), apply_micro(M)}. + +apply_micro(M) -> + {GC0, Words0, _} = statistics(garbage_collection), + statistics(reductions), + Before = erlang:now(), + + Compensate = apply_micro(M#micro.function, M#micro.loops), + After = erlang:now(), + {GC1, Words1, _} = statistics(garbage_collection), + {_, Reds} = statistics(reductions), + Elapsed = subtr(Before, After), + MicroSecs = Elapsed - Compensate, + [{title, M#micro.str}, + {tt1, M#micro.tt1}, + {function, M#micro.function}, + {weight_percentage, M#micro.weight}, + {loops, M#micro.loops}, + {microsecs,MicroSecs}, + {estones, (M#micro.weight * M#micro.weight * ?STONEFACTOR) div MicroSecs}, + {gcs, GC1 - GC0}, + {kilo_word_reclaimed, (Words1 - Words0) div 1000}, + {kilo_reductions, Reds div 1000}, + {gc_intensity, gci(Elapsed, GC1 - GC0, Words1 - Words0)}]. + + +subtr(Before, After) -> + (element(1,After)*1000000000000 + +element(2,After)*1000000+element(3,After)) - + (element(1,Before)*1000000000000 + +element(2,Before)*1000000+element(3,Before)). + +gci(Micros, Words, Gcs) -> + ((256 * Gcs) / Micros) + (Words / Micros). + +apply_micro(Name, Loops) -> + io:format("~w(~w)~n", [Name, Loops]), + apply(?MODULE, Name, [Loops]). + +%%%%%%%%%%%% micro bench manipulating lists. %%%%%%%%%%%%%%%%%%%%%%%%% +lists(I) -> + L1 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + L2 = "aaaaaaaaaa", + lists(I, L1, L2). + +lists(0, _,_) -> + 0; +lists(I, L1, L2) -> + revt(10, L1), + appt(10, L1, L2), + lists(I-1, L1, L2). + +revt(0, _) -> + done; +revt(I, L) -> + reverse(L), + revt(I-1, L). + +reverse(L) -> + reverse(L, []). +reverse([H|T], Ack) -> reverse(T, [H|Ack]); +reverse([], Ack) -> Ack. + +append([H|T], L) -> + [H | append(T, L)]; +append([], L) -> + L. + +appt(0, _L1, _L2) -> ok; +appt(I, L1, L2) -> + append(L1, L2), + appt(I-1, L1, L2). + + +%%%%%%%%%%%%%%% small message passing and ctxt switching %%%%%%% +msgp(I) -> + msgp(I, small()). + +msgp(0, _) -> + 0; +msgp(I, Msg) -> + P1 = spawn(?MODULE, p1, [self()]), + P2 = spawn(?MODULE, p1, [P1]), + P3 = spawn(?MODULE, p1, [P2]), + P4 = spawn(?MODULE, p1, [P3]), + msgp_loop(100, P4, Msg), + msgp(I-1, Msg). + +p1(To) -> + receive + {_From, {message, X}} -> + To ! {self(), {message, X}}, + p1(To); + stop -> + To ! stop, + exit(normal) + end. + +msgp_loop(0, P, _) -> + P ! stop, + receive + stop -> ok + end; +msgp_loop(I, P, Msg) -> + P ! {self(), {message, Msg}}, + receive + {_From, {message, _}} -> + msgp_loop(I-1, P, Msg) + end. + +%%%%%%%%%%%% large massage passing and ctxt switching %%%%%%% +msgp_medium(I) -> + msgp_medium(I, big()). + +msgp_medium(0, _) -> + 0; +msgp_medium(I, Msg) -> + P1 = spawn(?MODULE , p1, [self()]), + P2 = spawn(?MODULE, p1, [P1]), + P3 = spawn(?MODULE, p1, [P2]), + P4 = spawn(?MODULE, p1, [P3]), + msgp_loop(100, P4, Msg), + msgp_medium(I-1, Msg). + + + +%%%%%%%%%%%% huge massage passing and ctxt switching %%%%%%% +msgp_huge(I) -> + msgp_huge(I, very_big(15)). + +msgp_huge(0, _) -> + 0; +msgp_huge(I, Msg) -> + P1 = spawn(?MODULE , p1, [self()]), + P4 = spawn(?MODULE, p1, [P1]), + msgp_loop(100, P4, Msg), + msgp_huge(I-1, Msg). + + +%%%%%% typical protocol pattern matching %%%%%%% +pattern(0) -> + 0; +pattern(I) -> + Tail = "aaabbaaababba", + P1 = [0, 1,2,3,4,5|Tail], + pat_loop1(100, P1), + pat_loop2(100, P1), + pat_loop3(100, P1), + pat_loop4(100, P1), + pat_loop5(100, P1), + pattern(I-1). + +pat_loop1(0, _) -> + ok; +pat_loop1(_I, [_, _X, _Y, 0 |_T]) -> + ok; +pat_loop1(_I, [_, _X, _Y, 1| _T]) -> + ok; +pat_loop1(_I, [_, _X, _Y, 2 | _T]) -> + ok; +pat_loop1(I, [_, X, Y, 3 | T]) -> + pat_loop1(I-1, [0, X,Y,3|T]). + +pat_loop2(0, _) -> + ok; +pat_loop2(_I, [_X, Y | _Tail]) when Y bsl 1 == 0 -> + ok; +pat_loop2(_I, [_X, Y | _Tail]) when Y bsl 2 == 0 -> + ok; +pat_loop2(I, [X, Y | Tail]) when Y bsl 2 == 4 -> + pat_loop2(I-1, [X, Y |Tail]). + + +pat_loop3(0, _) -> + ok; +pat_loop3(_I, [{c, h} | _Tail]) -> + ok; +pat_loop3(_I, [1, 0 |_T]) -> + ok; +pat_loop3(_I, [X, _Y |_Tail]) when is_binary(X), size(X) == 1 -> + ok; +pat_loop3(_I, [no, _Y|_Tail]) -> + ok; +pat_loop3(_I, []) -> + ok; +pat_loop3(_I, [X,_Y|_T]) when X /= 0 -> + ok; +pat_loop3(_I, [2,3|_T]) -> + ok; +pat_loop3(_I, [1, 2]) -> + ok; +pat_loop3(I, [0, 1 |T]) -> + pat_loop3(I-1, [0,1|T]). + + +pat_loop4(0, _) -> ok; +pat_loop4(_I, [20|_T]) -> ok; +pat_loop4(_I, [219|_T]) -> ok; +pat_loop4(_I, [18|_T]) -> ok; +pat_loop4(_I, [17|_T]) -> ok; +pat_loop4(_I, [16|_T]) -> ok; +pat_loop4(_I, [15|_T]) -> ok; +pat_loop4(_I, [14|_T]) -> ok; +pat_loop4(_I, [13|_T]) -> ok; +pat_loop4(_I, [12|_T]) -> ok; +pat_loop4(_I, [11|_T]) -> ok; +pat_loop4(_I, [10|_T]) -> ok; +pat_loop4(_I, [9|_T]) -> ok; +pat_loop4(_I, [8|_T]) -> ok; +pat_loop4(_I, [7|_T]) -> ok; +pat_loop4(_I, [6|_T]) -> ok; +pat_loop4(_I, [5|_T]) -> ok; +pat_loop4(_I, [4|_T]) -> ok; +pat_loop4(_I, [3|_T]) -> ok; +pat_loop4(_I, [1|_T]) -> ok; +pat_loop4(_I, [21|_T]) -> ok; +pat_loop4(_I, [22|_T]) -> ok; +pat_loop4(_I, [23|_T]) -> ok; +pat_loop4(_I, [24|_T]) -> ok; +pat_loop4(_I, [25|_T]) -> ok; +pat_loop4(_I, [26|_T]) -> ok; +pat_loop4(_I, [27|_T]) -> ok; +pat_loop4(I, [0|T]) -> + pat_loop4(I-1, [0|T]). + +pat_loop5(0, _) -> ok; +pat_loop5(_I, [0, 20|_T]) -> ok; +pat_loop5(_I, [0, 19|_T]) -> ok; +pat_loop5(_I, [0, 18|_T]) -> ok; +pat_loop5(_I, [0, 17|_T]) -> ok; +pat_loop5(_I, [0, 16|_T]) -> ok; +pat_loop5(_I, [0, 15|_T]) -> ok; +pat_loop5(_I, [0, 14|_T]) -> ok; +pat_loop5(_I, [0, 13|_T]) -> ok; +pat_loop5(_I, [0, 12|_T]) -> ok; +pat_loop5(_I, [0, 11|_T]) -> ok; +pat_loop5(_I, [0, 10|_T]) -> ok; +pat_loop5(_I, [0, 9|_T]) -> ok; +pat_loop5(_I, [0, 8|_T]) -> ok; +pat_loop5(_I, [0, 7|_T]) -> ok; +pat_loop5(_I, [0, 6|_T]) -> ok; +pat_loop5(I, [0, 1|T]) -> + pat_loop5(I-1, [0,1|T]). + +%%%%%%%%%% term traversal representing simple pattern matchhing %%% +%%%%%%%%% + some arith +trav(I) -> + X = very_big(10), + trav(I, X). + +trav(0, _) -> 0; +trav(I, T) -> + do_trav(T), + trav(I-1, T). + +do_trav(T) when is_tuple(T) -> + tup_trav(T, 1, 1 + size(T)); +do_trav([H|T]) -> + do_trav(H) + do_trav(T); +do_trav(X) when is_integer(X) -> 1; +do_trav(_X) -> 0. +tup_trav(_T, P, P) -> 0; +tup_trav(T, P, End) -> + do_trav(element(P, T)) + tup_trav(T, P+1, End). + + +%% Port I/O +port_io(I) -> + EstoneCat = get(estone_cat), + Before = erlang:now(), + Pps = make_port_pids(5, I, EstoneCat), %% 5 ports + send_procs(Pps, go), + After = erlang:now(), + wait_for_pids(Pps), + subtr(Before, After). + +make_port_pids(0, _, _) -> + []; +make_port_pids(NoPorts, J, EstoneCat) -> + [spawn(?MODULE, ppp, [self(),J,EstoneCat]) | make_port_pids(NoPorts-1, J, EstoneCat)]. +ppp(Top, I, EstoneCat) -> + P = open_port({spawn, EstoneCat}, []),%% cat sits at the other end + Str = lists:duplicate(200, 88), %% 200 X'es + Cmd = {self(), {command, Str}}, + receive + go -> ok + end, + ppp_loop(P, I, Cmd), + Cmd2 = {self(), {command, "abcde"}}, + Res = ppp_loop(P, I, Cmd2), + P ! {self(), close}, + receive + {P, closed} -> + closed + end, + Top ! {self(), Res}. + +ppp_loop(_P, 0, _) -> + ok; +ppp_loop(P, I, Cmd) -> + P ! Cmd, + receive + {P, _} -> %% no match + ppp_loop(P, I-1, Cmd) + end. + +%% Working with a very large non-working data set +%% where the passive data resides in remote processes +large_dataset_work(I) -> + {Minus, Ps} = timer:tc(?MODULE, mk_big_procs, [?BIGPROCS]), + trav(I), + lists(I), + send_procs(Ps, stop), + Minus. %% Don't count time to create the big procs. + +mk_big_procs(0) -> []; +mk_big_procs(I) -> + [ mk_big_proc()| mk_big_procs(I-1)]. + +mk_big_proc() -> + P = spawn(?MODULE, big_proc, []), + P ! {self(), running}, + receive + {P, yes} -> P + end. + +big_proc() -> + X = very_big(?BIGPROC_SIZE), %% creates a big heap + Y = very_big(?BIGPROC_SIZE), + Z = very_big(?BIGPROC_SIZE), + + receive + {From, running} -> + From ! {self(), yes} + end, + receive + stop -> + {X, Y, Z} %% Can't be garbed away now by very (not super) + %% smart compiler + end. + +%% Working with a large non-working data set +%% where the data resides in the local process. +large_local_dataset_work(I) -> + {Minus, _Data} = timer:tc(?MODULE, very_big, [?BIGPROC_SIZE]), + trav(I), + lists(I), + Minus. + + +%% Fast allocation and also deallocation that is gc test +%% Important to not let variable linger on the stack un-necessarily +alloc(0) -> 0; +alloc(I) -> + _X11 = very_big(), + _X12 = very_big(), + _X13 = very_big(), + _Z = [_X14 = very_big(), + _X15 = very_big(), + _X16 = very_big()], + _X17 = very_big(), + _X18 = very_big(), + _X19 = very_big(), + _X20 = very_big(), + _X21 = very_big(), + _X22 = very_big(), + _X23 = very_big(), + _X24 = very_big(), + alloc(I-1). + +%% Time to call bif's +%% Lot's of element stuff which reflects the record code which +%% is becomming more and more common +bif_dispatch(0) -> + 0; +bif_dispatch(I) -> + disp(), disp(), disp(), disp(), disp(), disp(), + disp(), disp(), disp(), disp(), disp(), disp(), + bif_dispatch(I-1). + +disp() -> + Tup = {a}, + L = [x], + self(),self(),self(),self(),self(),self(),self(),self(),self(), + make_ref(), + atom_to_list(''), + _X = list_to_atom([]), + tuple_to_list({}), + _X2 = list_to_tuple([]), + element(1, Tup), + element(1, Tup), + _Elem = element(1, Tup),element(1, Tup),element(1, Tup),element(1, Tup), + element(1, Tup),element(1, Tup),element(1, Tup),element(1, Tup), + element(1, Tup),element(1, Tup),element(1, Tup),element(1, Tup), + element(1, Tup),element(1, Tup),element(1, Tup),element(1, Tup), + setelement(1, Tup,k), + setelement(1, Tup,k), + setelement(1, Tup,k),setelement(1, Tup,k),setelement(1, Tup,k), + setelement(1, Tup,k),setelement(1, Tup,k),setelement(1, Tup,k), + setelement(1, Tup,k), + setelement(1, Tup,k), + setelement(1, Tup,k), + setelement(1, Tup,k), + _Y = setelement(1, Tup,k), + _Date = date(), time(), + put(a, 1), + get(a), + erase(a), + hd(L), + tl(L), + _Len = length(L),length(L),length(L),length(L), + node(),node(),node(),node(),node(),node(),node(),node(), + S=self(), + node(S),node(S),node(S), + size(Tup), + _W = whereis(code_server),whereis(code_server), + whereis(code_server),whereis(code_server), + whereis(code_server),whereis(code_server), + _W2 = whereis(code_server). + + +%% Generic server like behaviour +generic(I) -> + register(funky, spawn(?MODULE, gserv, [funky, ?MODULE, [], []])), + g_loop(I). + +g_loop(0) -> + exit(whereis(funky), kill), + 0; +g_loop(I) -> + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [xyz]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [xyz]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + ?MODULE:req(funky, {call, [abc]}), + g_loop(I-1). + +req(Name, Req) -> + R = make_ref(), + Name ! {self(), R, Req}, + receive + {Name, R, Reply} -> Reply + after 2000 -> + exit(timeout) + end. + +gserv(Name, Mod, State, Debug) -> + receive + {From, Ref, {call, Req}} when Debug == [] -> + case catch apply(Mod, handle_call, [From, State, Req]) of + {reply, Reply, State2} -> + From ! {Name, Ref, Reply}, + gserv(Name, Mod, State2, Debug); + {noreply, State2} -> + gserv(Name, Mod, State2, Debug); + {'EXIT', Reason} -> + exit(Reason) + end; + {_From, _Ref, _Req} when Debug /= [] -> + exit(nodebug) + end. + +handle_call(_From, _State, [xyz]) -> + R = atom_to_list(xyz), + {reply, R, []}; +handle_call(_From, State, [abc]) -> + R = 1 + 3, + {reply, R, [R | State]}. + + + +%% Binary handling, creating, manipulating and sending binaries +binary_h(I) -> + Before = erlang:now(), + P = spawn(?MODULE, echo, [self()]), + B = list_to_binary(lists:duplicate(2000, 5)), + After = erlang:now(), + Compensate = subtr(Before, After), + binary_h_2(I, P, B), + Compensate. + +binary_h_2(0, P, _B) -> + exit(P, kill); +binary_h_2(I, P, B) -> + echo_loop(P, 20, B), + split_loop(B, {abc,1,2222,self(),"ancnd"}, 100), + binary_h_2(I-1, P, B). + +split_loop(_B, _, 0) -> + ok; +split_loop(B, Term, I) -> + {X, Y} = split_binary(B, I), + size(X), + binary_to_list(Y, 1, 2), + binary_to_term(term_to_binary(Term)), + split_loop(B, Term, I-1). + + +echo_loop(_P, 0, _B) -> + k; +echo_loop(P, I, B) -> + P ! B, + P ! B, + P ! B, + P ! B, + P ! B, + P ! B, + P ! B, + P ! B, + P ! B, + P ! B, + receive _ -> ok end, + receive _ -> ok end, + receive _ -> ok end, + receive _ -> ok end, + receive _ -> ok end, + receive _ -> ok end, + receive _ -> ok end, + receive _ -> ok end, + receive _ -> ok end, + receive _ -> ok end, + echo_loop(P, I-1, B). + + +ets(0) -> + 0; +ets(I) -> + T1 = ets:new(a, [set]), + T2 = ets:new(c, [bag, private]), + L = [T1, T2], + run_tabs(L, L, 1), + ets:delete(T1), + ets:delete(T2), + ets(I-1). + +run_tabs(_, _, 0) -> + ok; +run_tabs([], L, I) -> + run_tabs(L, L, I-1); +run_tabs([Tab|Tail], L, I) -> + Begin = I * 20, + End = (I+1) * 20, + run_tab(Tab, Begin, End, I), + run_tabs(Tail, L, I). + +run_tab(_Tab, X, X, _) -> + ok; +run_tab(Tab, Beg, End, J) -> + ets:insert(Tab, {Beg, J}), + ets:insert(Tab, {J, Beg}), + ets:insert(Tab, {{foo,Beg}, J}), + ets:insert(Tab, {{foo, J}, Beg}), + ets:delete(Tab, haha), + ets:match_delete(Tab, {k, j}), + ets:match(Tab, {Beg, '$1'}), + ets:match(Tab, {'$1', J}), + ets:delete(Tab, Beg), + K = ets:first(Tab), + _K2 = ets:next(Tab, K), + run_tab(Tab, Beg+1, End, J). + + +%%%% Integer arith %%%%% +int_arith(0) -> + 0; +int_arith(I) -> + do_arith(I) + + do_arith(I) + + do_arith(I) + + do_arith(I) + + do_arith(I) + + do_arith(I) + + do_arith(I) + + do_arith(I) + + do_arith(I) + + 66, + int_arith(I-1). + +do_arith(I) -> + do_arith2(I) - + do_arith2(I) - + do_arith2(I) - + do_arith2(I) - + do_arith2(I) - + do_arith2(I) - + do_arith2(I) - + 99. + +do_arith2(I) -> + X = 23, + _Y = 789 + I, + Z = I + 1, + U = (X bsl 1 bsr I) * X div 2 bsr 4, + U1 = Z + Z + Z + Z + X bsl 4 * 2 bsl 2, + Z - U + U1 div 2. + + +%%%% Float arith %%%%% +float_arith(0) -> + 0; +float_arith(I) -> + f_do_arith(I) + + f_do_arith(I) + + f_do_arith(I) + + f_do_arith(I) + + f_do_arith(I) + + f_do_arith(I) + + f_do_arith(I) + + f_do_arith(I) + + f_do_arith(I) + + 66, + float_arith(I-1). + +f_do_arith(I) -> + X = 23.4, + _Y = 789.99 + I, + Z = I + 1.88, + U = (X * 1 / I) * X / 2 * 4, + U1 = Z + Z + Z + Z + X * 4 * 2 / 2, + Z - U + U1 / 2. + +%%%% time to do various function calls +fcalls(0) -> + 0; +fcalls(I) -> + local0(400), + remote0(400), + app0(400), + local1(400), + remote1(400), + app1(400), + fcalls(I-1). + + +local0(0) -> 0; +local0(N) -> + local0(N-1). + +local1(0) -> 0; +local1(N) -> + 1+local1(N-1). + +remote0(0) -> 0; +remote0(N) -> + ?MODULE:remote0(N-1). + +remote1(0) -> 0; +remote1(N) -> + 1+?MODULE:remote1(N-1). + +app0(0) -> 0; +app0(N) -> + apply(?MODULE, app0, [N-1]). + +app1(0) -> 0; +app1(N) -> + 1 + apply(?MODULE, app1, [N-1]). + +%%%%%% jog the time queue implementation +timer(I) -> + L = [50, 50, 50, 100, 1000, 3000, 8000, 50000, 100000], + timer(I, L). + +timer(0, _) -> 0; +timer(N, L) -> + send_self(100), + recv(100,L, L), + timer(N-1). + +recv(0, _, _) -> + ok; +recv(N, [], L) -> + recv(N, L, L); +recv(N, [Timeout|Tail], L) -> + receive + hi_dude -> + recv(N-1, Tail, L) + after Timeout -> + io:format("XXXXX this wasn't supposed to happen???~n", []), + ok + end. + +send_self(0) -> + ok; +send_self(N) -> + self() ! hi_dude, + send_self(N-1). + + +%%%%%%%%%%%% managing many links %%%%% +links(I) -> + L = mk_link_procs(100), + send_procs(L, {procs, L, I}), + wait_for_pids(L), + 0. + +mk_link_procs(0) -> + []; +mk_link_procs(I) -> + [spawn_link(?MODULE, lproc, [self()]) | mk_link_procs(I-1)]. + + +lproc(Top) -> + process_flag(trap_exit,true), + receive + {procs, Procs, I} -> + Top ! {self(), lproc(Procs, Procs, link, I)} + end. + +lproc(_, _, _, 0) -> + done; +lproc([], Procs, link, I) -> + lproc(Procs, Procs, unlink, I-1); +lproc([], Procs, unlink, I) -> + lproc(Procs, Procs, link, I-1); +lproc([Pid|Tail], Procs, unlink, I) -> + unlink(Pid), + lproc(Tail, Procs, unlink, I); +lproc([Pid|Tail], Procs, link, I) -> + link(Pid), + lproc(Tail, Procs, unlink, I). + + + +%%%%%%%%%%% various utility functions %%%%%%% + +echo(Pid) -> + receive + X -> Pid ! X, + echo(Pid) + end. + +very_big() -> + very_big(2). +very_big(0) -> []; +very_big(I) -> + {1,2,3,a,v,f,r,t,y,u,self(), self(), self(), + "22222222222222222", {{"234", self()}}, + [[very_big(I-1)]]}. + +big() -> + {self(), funky_stuff, baby, {1, [123, true,[]], "abcdef"}}. + +small() -> {self(), true}. + +%% Wait for a list of children to respond +wait_for_pids([]) -> + ok; +wait_for_pids([P|Tail]) -> + receive + {P, _Res} -> wait_for_pids(Tail) + end. + +send_procs([P|Tail], Msg) -> P ! Msg, send_procs(Tail, Msg); +send_procs([], _) -> ok. + diff --git a/erts/emulator/test/estone_SUITE_data/Makefile.src b/erts/emulator/test/estone_SUITE_data/Makefile.src new file mode 100644 index 0000000000..bd5f155fdf --- /dev/null +++ b/erts/emulator/test/estone_SUITE_data/Makefile.src @@ -0,0 +1,15 @@ +CC = @CC@ +LD = @LD@ +CFLAGS = @CFLAGS@ @DEFS@ +CROSSLDFLAGS = @CROSSLDFLAGS@ + +PROG = estone_cat +PROGS = $(PROG)@exe@ + +all: $(PROGS) + +$(PROG)@exe@: $(PROG)@obj@ + $(LD) $(CROSSLDFLAGS) -o $(PROG) $(PROG)@obj@ @LIBS@ + +$(PROG)@obj@: $(PROG).c + $(CC) -c -o $(PROG)@obj@ $(CFLAGS) $(PROG).c diff --git a/erts/emulator/test/estone_SUITE_data/estone_cat.c b/erts/emulator/test/estone_SUITE_data/estone_cat.c new file mode 100644 index 0000000000..8ed9f8375b --- /dev/null +++ b/erts/emulator/test/estone_SUITE_data/estone_cat.c @@ -0,0 +1,40 @@ +/* + * Author: Bjorn Gustavsson + * Purpose: Simple portable cat utility for the estone benchmark. + * + * Compiling instructions: + * + * Unix: gcc -O2 -o estone_cat estone_cat.c + * Windows: cl -Ox estone_cat.c + */ + +#include <sys/types.h> +#include <fcntl.h> +#include <errno.h> + +#ifdef VXWORKS +estone_cat(argc, argv) +#else +main(argc, argv) +#endif +int argc; +char *argv[]; +{ + char buf[16384]; + int n; + +#ifdef _O_BINARY + _setmode(0, _O_BINARY); + _setmode(1, _O_BINARY); +#endif + + for (;;) { + n = read(0, buf, sizeof(buf)); + if (n <= 0 && errno == EINTR) + continue; + if (n <= 0) + break; + write(1, buf, n); + } + return 0; +} diff --git a/erts/emulator/test/estone_SUITE_data/sunspeed.sh b/erts/emulator/test/estone_SUITE_data/sunspeed.sh new file mode 100755 index 0000000000..d1bd5c4531 --- /dev/null +++ b/erts/emulator/test/estone_SUITE_data/sunspeed.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# +# sunspeed +# +# Returns CPU speed in Mhz on sun/solaris 5.x & 6.x +# + +echo `/usr/sbin/psrinfo -v | sed 's/.* \([0-9]*\)\ MHz.*/\1/;s/.*[^0-9].*//g'` | sed 's/ /+/g' + +#
\ No newline at end of file diff --git a/erts/emulator/test/evil_SUITE.erl b/erts/emulator/test/evil_SUITE.erl new file mode 100644 index 0000000000..a8288584f4 --- /dev/null +++ b/erts/emulator/test/evil_SUITE.erl @@ -0,0 +1,377 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(evil_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + heap_frag/1, + encode_decode_ext/1, + decode_integer_ext/1, + decode_small_big_ext/1, + decode_large_big_ext/1, + decode_small_big_ext_neg/1, + decode_large_big_ext_neg/1, + decode_too_small/1, + decode_pos_neg_zero/1 + ]). + +-include("test_server.hrl"). + +all(suite) -> + [ + heap_frag, + encode_decode_ext, + decode_integer_ext, + decode_small_big_ext, + decode_large_big_ext, + decode_small_big_ext_neg, + decode_large_big_ext_neg, + decode_too_small, + decode_pos_neg_zero + ]. + +init_per_testcase(_Case, Config) -> + ?line Dog = test_server:timetrap(?t:minutes(0.5)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +heap_frag(Config) when is_list(Config) -> + N = 512, + Self = self(), + ?line Pid = spawn_link(fun() -> appender(Self, N) end), + receive + {Pid,Res} -> + ?line Res = my_appender(N); + Garbage -> + io:format("Garbage: ~p\n", [Garbage]), + ?line ?t:fail(got_garbage) + end. + + +%% ######################################################################## %% + +%% "Interesting" integers taken from erl_interface ei_decode_SUITE.erl +%% These test cases are not "evil" but the next test case is.... + +encode_decode_ext(Config) when is_list(Config) -> + ?line enc_dec( 2, 0), % SMALL_INTEGER_EXT smallest + ?line enc_dec( 2, 255), % SMALL_INTEGER_EXT largest + ?line enc_dec( 5, 256), % INTEGER_EXT smallest pos (*) + ?line enc_dec( 5, -1), % INTEGER_EXT largest neg + + ?line enc_dec( 5, 16#07ffffff), % INTEGER_EXT largest (28 bits) + ?line enc_dec( 5,-16#08000000), % INTEGER_EXT smallest + ?line enc_dec( 7, 16#08000000), % SMALL_BIG_EXT smallest pos(*) + ?line enc_dec( 7,-16#08000001), % SMALL_BIG_EXT largest neg (*) + + ?line enc_dec( 7, 16#7fffffff), % SMALL_BIG_EXT largest i32 + ?line enc_dec( 7,-16#80000000), % SMALL_BIG_EXT smallest i32 + + ?line enc_dec( 7, 16#80000000), % SMALL_BIG_EXT u32 + ?line enc_dec( 7, 16#ffffffff), % SMALL_BIG_EXT largest u32 + + ?line enc_dec( 9, 16#7fffffffffff), % largest i48 + ?line enc_dec( 9,-16#800000000000), % smallest i48 + ?line enc_dec( 9, 16#ffffffffffff), % largest u48 + ?line enc_dec(11, 16#7fffffffffffffff), % largest i64 + ?line enc_dec(11,-16#8000000000000000), % smallest i64 + ?line enc_dec(11, 16#ffffffffffffffff), % largest u64 + + ok. + + +%% ######################################################################## %% + +%% "Interesting" integers taken from erl_interface ei_decode_SUITE.erl +%% These test the decoding "unusual", i.e. integers packed according +%% to "erts/emulator/internal_doc/erl_ext_dist.txt" but not the way +%% the emulator or erl_interface encode them. +%% +%% NOTE!!!! The comments below after a decode line is how it currently +%% is encoded in the external format by the emulator and +%% erl_interface, i.e. not how it is encoded in the test case below. + +decode_integer_ext(Config) when is_list(Config) -> + ?line decode( 0, <<131,98, 0:32>>), % SMALL_INTEGER_EXT + ?line decode( 42, <<131,98, 42:32>>), % SMALL_INTEGER_EXT + ?line decode(255, <<131,98,255:32>>), % SMALL_INTEGER_EXT + ?line decode( 16#08000000, <<131,98, 16#08000000:32>>), % SMALL_BIG_EXT + ?line decode(-16#08000001, <<131,98,-16#08000001:32>>), % SMALL_BIG_EXT + ?line decode( 16#7fffffff, <<131,98, 16#7fffffff:32>>), % SMALL_BIG_EXT + ?line decode(-16#80000000, <<131,98,-16#80000000:32>>), % SMALL_BIG_EXT + ok. + +decode_small_big_ext(Config) when is_list(Config) -> + ?line decode(256,<<131,110,2,0,0,1>>), % INTEGER_EXT + ?line decode(16#07ffffff,<<131,110,4,0,255,255,255,7>>), % INTEGER_EXT + ?line decode(16#7fffffff,<<131,110,4,0,255,255,255,127>>), % SMALL_BIG_EXT + + ?line decode(42,<<131,110,1,0,42>>), % SMALL_INTEGER_EXT + ?line decode(42,<<131,110,2,0,42,0>>), % Redundant zeros from now on + ?line decode(42,<<131,110,3,0,42,0,0>>), + ?line decode(42,<<131,110,4,0,42,0,0,0>>), + ?line decode(42,<<131,110,5,0,42,0,0,0,0>>), + ?line decode(42,<<131,110,6,0,42,0,0,0,0,0>>), + ?line decode(42,<<131,110,7,0,42,0,0,0,0,0,0>>), + ?line decode(42,<<131,110,8,0,42,0,0,0,0,0,0,0>>), + ok. + +decode_large_big_ext(Config) when is_list(Config) -> + ?line decode(256,<<131,111,2:32,0,0,1>>), % INTEGER_EXT + ?line decode(16#07ffffff,<<131,111,4:32,0,255,255,255,7>>), % INTEG_EXT + ?line decode(16#7fffffff,<<131,111,4:32,0,255,255,255,127>>), % SMA_BIG + ?line decode(16#ffffffff,<<131,111,4:32,0,255,255,255,255>>), % SMA_BIG + + N = largest_small_big(), + ?line decode(N,<<131,111,255:32,0,N:2040/little>>), % SMALL_BIG_EXT + + ?line decode(42,<<131,111,1:32,0,42>>), + ?line decode(42,<<131,111,2:32,0,42,0>>), % Redundant zeros from now on + ?line decode(42,<<131,111,3:32,0,42,0,0>>), + ?line decode(42,<<131,111,4:32,0,42,0,0,0>>), + ?line decode(42,<<131,111,5:32,0,42,0,0,0,0>>), + ?line decode(42,<<131,111,6:32,0,42,0,0,0,0,0>>), + ?line decode(42,<<131,111,7:32,0,42,0,0,0,0,0,0>>), + ?line decode(42,<<131,111,8:32,0,42,0,0,0,0,0,0,0>>), + ok. + +decode_small_big_ext_neg(Config) when is_list(Config) -> + ?line decode(-1,<<131,110,1,1,1>>), % INTEGER_EXT + ?line decode(-16#08000000,<<131,110,4,1,0,0,0,8>>), % INTEGER_EXT + ?line decode(-16#80000000,<<131,110,4,1,0,0,0,128>>), % SMALL_BIG_EXT + ?line decode(-16#ffffffff,<<131,110,4,1,255,255,255,255>>), % SMALL_BIG_EXT + + N = largest_small_big(), + ?line decode(-N,<<131,111,255:32,1,N:2040/little>>), % SMALL_BIG_EXT + + ?line decode(-42,<<131,110,1,1,42>>), + ?line decode(-42,<<131,110,2,1,42,0>>), % Redundant zeros from now on + ?line decode(-42,<<131,110,3,1,42,0,0>>), + ?line decode(-42,<<131,110,4,1,42,0,0,0>>), + ?line decode(-42,<<131,110,5,1,42,0,0,0,0>>), + ?line decode(-42,<<131,110,6,1,42,0,0,0,0,0>>), + ?line decode(-42,<<131,110,7,1,42,0,0,0,0,0,0>>), + ?line decode(-42,<<131,110,8,1,42,0,0,0,0,0,0,0>>), + ok. + +decode_large_big_ext_neg(Config) when is_list(Config) -> + ?line decode(-1,<<131,111,1:32,1,1>>), % INTEGER_EXT + ?line decode(-16#08000000,<<131,111,4:32,1,0,0,0,8>>), % INTEGER_EXT + ?line decode(-16#80000000,<<131,111,4:32,1,0,0,0,128>>), % SMALL_BIG_EXT + + ?line decode(-42,<<131,111,1:32,1,42>>), + ?line decode(-42,<<131,111,2:32,1,42,0>>), % Redundant zeros from now on + ?line decode(-42,<<131,111,3:32,1,42,0,0>>), + ?line decode(-42,<<131,111,4:32,1,42,0,0,0>>), + ?line decode(-42,<<131,111,5:32,1,42,0,0,0,0>>), + ?line decode(-42,<<131,111,6:32,1,42,0,0,0,0,0>>), + ?line decode(-42,<<131,111,7:32,1,42,0,0,0,0,0,0>>), + ?line decode(-42,<<131,111,8:32,1,42,0,0,0,0,0,0,0>>), + ok. + +decode_pos_neg_zero(Config) when is_list(Config) -> + ?line decode( 0, <<131,110,0,0>>), % SMALL_BIG_EXT (positive zero) + ?line decode( 0, <<131,110,1,0,0>>), % SMALL_BIG_EXT (positive zero) + ?line decode( 0, <<131,110,0,1>>), % SMALL_BIG_EXT (negative zero) + ?line decode( 0, <<131,110,1,1,0>>), % SMALL_BIG_EXT (negative zero) + + ?line decode( 0, <<131,111,0:32,0>>), % SMALL_BIG_EXT (positive zero) + ?line decode( 0, <<131,111,1:32,0,0>>), % SMALL_BIG_EXT (positive zero) + ?line decode( 0, <<131,111,0:32,1>>), % SMALL_BIG_EXT (negative zero) + ?line decode( 0, <<131,111,1:32,1,0>>), % SMALL_BIG_EXT (negative zero) + + N = largest_small_big(), + ?line decode( N,<<131,110,255,0,N:2040/little>>), % largest SMALL_BIG_EXT + ?line decode(-N,<<131,110,255,1,N:2040/little>>), % largest SMALL_BIG_EXT + + ok. + +%% Test to decode uncompleted encodings for all in "erl_ext_dist.txt" + +decode_too_small(Config) when is_list(Config) -> + ?line decode_badarg(<<131, 97>>), + ?line decode_badarg(<<131, 98>>), + ?line decode_badarg(<<131, 98, 0>>), + ?line decode_badarg(<<131, 98, 0, 0>>), + ?line decode_badarg(<<131, 98, 0, 0, 0>>), + ?line decode_badarg(<<131, 99>>), + ?line decode_badarg(<<131, 99, 0>>), + ?line decode_badarg(<<131, 99, 0:240>>), + + ?line decode_badarg(<<131,100>>), + ?line decode_badarg(<<131,100, 1:16/big>>), + ?line decode_badarg(<<131,100, 2:16/big>>), + ?line decode_badarg(<<131,100, 2:16/big, "A">>), + + % FIXME node name "A" seem ok, should it be? +% ?line decode_badarg(<<131,101,100,1:16/big,"A",42:32/big,0>>), + + ?line decode_badarg(<<131,101>>), + ?line decode_badarg(<<131,101,106>>), + ?line decode_badarg(<<131,101,255>>), + ?line decode_badarg(<<131,101,106,42:8/big>>), + ?line decode_badarg(<<131,101,106,42:16/big>>), + ?line decode_badarg(<<131,101,255,42:24/big>>), + ?line decode_badarg(<<131,101,255,42:32/big,0>>), + ?line decode_badarg(<<131,101,100,1:16/big,"A">>), + ?line decode_badarg(<<131,101,100,1:16/big,"A",42:32/big>>), + + ?line decode_badarg(<<131,102>>), + ?line decode_badarg(<<131,102,106,42:32/big,0>>), + ?line decode_badarg(<<131,102,255,42:32/big,0>>), + ?line decode_badarg(<<131,102,100,1:16/big,"A">>), + ?line decode_badarg(<<131,102,100,1:16/big,"A",42:32/big>>), + + ?line decode_badarg(<<131,103>>), + ?line decode_badarg(<<131,103,106,42:32/big,0>>), + ?line decode_badarg(<<131,103,255,42:32/big,0>>), + ?line decode_badarg(<<131,103,100,1:16/big,"A">>), + ?line decode_badarg(<<131,103,100,1:16/big,"A",42:32/big>>), + ?line decode_badarg(<<131,103,100,1:16/big,"A",4:32/big,2:32/big>>), + + ?line decode_badarg(<<131,104>>), + ?line decode_badarg(<<131,104, 1>>), + ?line decode_badarg(<<131,104, 2, 106>>), + ?line decode_badarg(<<131,105, 1:32/big>>), + ?line decode_badarg(<<131,105, 2:32/big, 106>>), + + ?line decode_badarg(<<131,107>>), + ?line decode_badarg(<<131,107, 1:16/big>>), + ?line decode_badarg(<<131,107, 2:16/big>>), + ?line decode_badarg(<<131,107, 2:16/big, "A">>), + + ?line decode_badarg(<<131,108>>), + ?line decode_badarg(<<131,108, 1:32/big>>), + ?line decode_badarg(<<131,108, 2:32/big>>), + ?line decode_badarg(<<131,108, 2:32/big, 106>>), % FIXME don't use NIL + + ?line decode_badarg(<<131,109>>), + ?line decode_badarg(<<131,109, 1:32/big>>), + ?line decode_badarg(<<131,109, 2:32/big>>), + ?line decode_badarg(<<131,109, 2:32/big, 42>>), + + N = largest_small_big(), + + ?line decode_badarg(<<131,110>>), + ?line decode_badarg(<<131,110,1>>), + ?line decode_badarg(<<131,110,1,0>>), + ?line decode_badarg(<<131,110,1,1>>), + ?line decode_badarg(<<131,110,2,0,42>>), + ?line decode_badarg(<<131,110,2,1,42>>), + ?line decode_badarg(<<131,110,255,0,N:2032/little>>), + ?line decode_badarg(<<131,110,255,1,N:2032/little>>), + + ?line decode_badarg(<<131,111>>), + ?line decode_badarg(<<131,111, 1:32/big>>), + ?line decode_badarg(<<131,111, 1:32/big,0>>), + ?line decode_badarg(<<131,111, 1:32/big,1>>), + ?line decode_badarg(<<131,111, 2:32/big,0,42>>), + ?line decode_badarg(<<131,111, 2:32/big,1,42>>), + ?line decode_badarg(<<131,111,256:32/big,0,N:2032/little>>), + ?line decode_badarg(<<131,111,256:32/big,1,N:2032/little>>), + ?line decode_badarg(<<131,111,256:32/big,0,N:2040/little>>), + ?line decode_badarg(<<131,111,256:32/big,1,N:2040/little>>), + ?line decode_badarg(<<131,111,257:32/big,0,N:2048/little>>), + ?line decode_badarg(<<131,111,257:32/big,1,N:2048/little>>), + + % Emulator dies if trying to create large bignum.... +% ?line decode_badarg(<<131,111,16#ffffffff:32/big,0>>), +% ?line decode_badarg(<<131,111,16#ffffffff:32/big,1>>), + + ?line decode_badarg(<<131, 78>>), + ?line decode_badarg(<<131, 78, 42>>), + ?line decode_badarg(<<131, 78, 42, 1>>), + ?line decode_badarg(<<131, 78, 42, 1:16/big>>), + ?line decode_badarg(<<131, 78, 42, 2:16/big>>), + ?line decode_badarg(<<131, 78, 42, 2:16/big, "A">>), + + ?line decode_badarg(<<131, 67>>), + + ?line decode_badarg(<<131,114>>), + ?line decode_badarg(<<131,114,0>>), + ?line decode_badarg(<<131,114,1:16/big>>), + ?line decode_badarg(<<131,114,1:16/big,100>>), + ?line decode_badarg(<<131,114,1:16/big,100,1:16/big>>), + ?line decode_badarg(<<131,114,1:16/big,100,1:16/big,"A">>), + ?line decode_badarg(<<131,114,1:16/big,100,1:16/big,"A",0>>), + ?line decode_badarg(<<131,114,1:16/big,100,1:16/big,"A",0,42:8>>), + ?line decode_badarg(<<131,114,1:16/big,100,1:16/big,"A",0,42:16>>), + ?line decode_badarg(<<131,114,1:16/big,100,1:16/big,"A",0,42:24>>), + + ?line decode_badarg(<<131,117>>), % FIXME needs more tests + + ok. + +%% ######################################################################## %% + +decode_badarg(Bin) -> + io:format("Trying ~w\n",[Bin]), + {'EXIT',{badarg,_}} = (catch binary_to_term(Bin)). + +enc_dec(_Size, Term) -> + Bin = term_to_binary(Term), + Term = binary_to_term(Bin), + ok. + +decode(Term, Binary) -> + io:format("Encoding ~w to ~w ... ",[Binary,Term]), + NewTerm = binary_to_term(Binary), + io:format("got ~w\n",[NewTerm]), + Term = NewTerm. + +largest_small_big() -> + List = lists:duplicate(255,255), + Limbs = list_to_binary(List), + binary_to_term(<<131,110,255,0,Limbs/binary>>). + +%% ######################################################################## %% + +appender(Parent, N) -> + seed(), + Res = appender_1(N, {}), + Parent ! {self(),Res}. + +appender_1(0, T) -> T; +appender_1(N, T0) -> + U = rnd_term(), + T = erlang:append_element(T0, U), + appender_1(N-1, T). + +my_appender(N) -> + seed(), + my_appender_1(N, []). + +my_appender_1(0, T) -> + list_to_tuple(lists:reverse(T)); +my_appender_1(N, T0) -> + U = rnd_term(), + T = [U|T0], + my_appender_1(N-1, T). + +seed() -> + random:seed(3172, 9815, 20129). + +rnd_term() -> + U0 = random:uniform(), + B = <<U0/float>>, + {U0,U0 * 2.5 + 3.14,[U0*2.3,B]}. + diff --git a/erts/emulator/test/exception_SUITE.erl b/erts/emulator/test/exception_SUITE.erl new file mode 100644 index 0000000000..f1e6e004ad --- /dev/null +++ b/erts/emulator/test/exception_SUITE.erl @@ -0,0 +1,497 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(exception_SUITE). + +-export([all/1, badmatch/1, pending_errors/1, nil_arith/1, + stacktrace/1, nested_stacktrace/1, raise/1, gunilla/1, per/1, + exception_with_heap_frag/1]). + +-export([bad_guy/2]). + +-include("test_server.hrl"). +-import(lists, [foreach/2]). + +all(suite) -> + [badmatch, pending_errors, nil_arith, + stacktrace, nested_stacktrace, raise, gunilla, per, + exception_with_heap_frag]. + +-define(try_match(E), + catch ?MODULE:bar(), + {'EXIT', {{badmatch, nomatch}, _}} = (catch E = id(nomatch))). + +%% Test that deliberately bad matches are reported correctly. + +badmatch(Config) when is_list(Config) -> + ?line ?try_match(a), + ?line ?try_match(42), + ?line ?try_match({a, b, c}), + ?line ?try_match([]), + ?line ?try_match(1.0), + ok. + +%% Test various exceptions, in the presence of a previous error suppressed +%% in a guard. +pending_errors(Config) when is_list(Config) -> + ?line pending(e_badmatch, {badmatch, b}), + ?line pending(x, function_clause), + ?line pending(e_case, {case_clause, xxx}), + ?line pending(e_if, if_clause), + ?line pending(e_badarith, badarith), + ?line pending(e_undef, undef), + ?line pending(e_timeoutval, timeout_value), + ?line pending(e_badarg, badarg), + ?line pending(e_badarg_spawn, badarg), + ok. + +bad_guy(pe_badarith, Other) when Other+1 == 0 -> % badarith (suppressed) + ok; +bad_guy(pe_badarg, Other) when length(Other) > 0 -> % badarg (suppressed) + ok; +bad_guy(_, e_case) -> + case id(xxx) of + ok -> ok + end; % case_clause +bad_guy(_, e_if) -> + if + a == b -> ok + end; % if_clause +bad_guy(_, e_badarith) -> + 1+b; % badarith +bad_guy(_, e_undef) -> + non_existing_module:foo(); % undef +bad_guy(_, e_timeoutval) -> + receive + after arne -> % timeout_value + ok + end; +bad_guy(_, e_badarg) -> + node(xxx); % badarg +bad_guy(_, e_badarg_spawn) -> + spawn({}, {}, {}); % badarg +bad_guy(_, e_badmatch) -> + a = id(b). % badmatch + +pending(Arg, Expected) -> + pending(pe_badarith, Arg, Expected), + pending(pe_badarg, Arg, Expected). + +pending(First, Second, Expected) -> + pending_catched(First, Second, Expected), + pending_exit_message([First, Second], Expected). + +pending_catched(First, Second, Expected) -> + ok = io:format("Catching bad_guy(~p, ~p)", [First, Second]), + case catch bad_guy(First, Second) of + {'EXIT', Reason} -> + pending(Reason, bad_guy, [First, Second], Expected); + Other -> + test_server:fail({not_exit, Other}) + end. + +pending_exit_message(Args, Expected) -> + ok = io:format("Trapping EXITs from spawn_link(~p, ~p, ~p)", + [?MODULE, bad_guy, Args]), + process_flag(trap_exit, true), + Pid = spawn_link(?MODULE, bad_guy, Args), + receive + {'EXIT', Pid, Reason} -> + pending(Reason, bad_guy, Args, Expected); + Other -> + test_server:fail({unexpected_message, Other}) + after 10000 -> + test_server:fail(timeout) + end, + process_flag(trap_exit, false). + +pending({badarg, [{erlang,Bif,BifArgs},{?MODULE,Func,Arity}|_]}, Func, Args, _Code) + when is_atom(Bif), is_list(BifArgs), length(Args) == Arity -> + ok; +pending({undef,[{non_existing_module,foo,[]}|_]}, _, _, _) -> + ok; +pending({function_clause,[{?MODULE,Func,Args}|_]}, Func, Args, _Code) -> + ok; +pending({Code,[{?MODULE,Func,Arity}|_]}, Func, Args, Code) when length(Args) == Arity -> + ok; +pending(Reason, _Function, _Args, _Code) -> + test_server:fail({bad_exit_reason,Reason}). + +%% Test that doing arithmetics on [] gives a badarith EXIT and not a crash. + +nil_arith(Config) when is_list(Config) -> + ?line ba_plus_minus_times([], []), + + ?line ba_plus_minus_times([], 0), + ?line ba_plus_minus_times([], 42), + ?line ba_plus_minus_times([], 38724978123478923784), + ?line ba_plus_minus_times([], 38.72), + + ?line ba_plus_minus_times(0, []), + ?line ba_plus_minus_times(334, []), + ?line ba_plus_minus_times(387249797813478923784, []), + ?line ba_plus_minus_times(344.22, []), + + ?line ba_div_rem([], []), + + ?line ba_div_rem([], 0), + ?line ba_div_rem([], 1), + ?line ba_div_rem([], 42), + ?line ba_div_rem([], 38724978123478923784), + ?line ba_div_rem(344.22, []), + + ?line ba_div_rem(0, []), + ?line ba_div_rem(1, []), + ?line ba_div_rem(334, []), + ?line ba_div_rem(387249797813478923784, []), + ?line ba_div_rem(344.22, []), + + ?line ba_div_rem(344.22, 0.0), + ?line ba_div_rem(1, 0.0), + ?line ba_div_rem(392873498733971, 0.0), + + ?line ba_bop([], []), + ?line ba_bop(0, []), + ?line ba_bop(42, []), + ?line ba_bop(-42342742987343, []), + ?line ba_bop(238.342, []), + ?line ba_bop([], 0), + ?line ba_bop([], -243), + ?line ba_bop([], 243), + ?line ba_bop([], 2438724982478933), + ?line ba_bop([], 3987.37), + + ?line ba_bnot([]), + ?line ba_bnot(23.33), + + ?line ba_shift([], []), + ?line ba_shift([], 0), + ?line ba_shift([], 4), + ?line ba_shift([], -4), + ?line ba_shift([], 2343333333333), + ?line ba_shift([], -333333333), + ?line ba_shift([], 234.00), + ?line ba_shift(23, []), + ?line ba_shift(0, []), + ?line ba_shift(-3433443433433323, []), + ?line ba_shift(433443433433323, []), + ?line ba_shift(343.93, []), + ok. + +ba_plus_minus_times(A, B) -> + io:format("~p + ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A + B), + io:format("~p - ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A - B), + io:format("~p * ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A * B). + +ba_div_rem(A, B) -> + io:format("~p / ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A / B), + io:format("~p div ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A div B), + io:format("~p rem ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A rem B). + +ba_bop(A, B) -> + io:format("~p band ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A band B), + io:format("~p bor ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A bor B), + io:format("~p bxor ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A bxor B). + +ba_shift(A, B) -> + io:format("~p bsl ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A bsl B), + io:format("~p bsr ~p", [A, B]), + {'EXIT', {badarith, _}} = (catch A bsr B). + +ba_bnot(A) -> + io:format("bnot ~p", [A]), + {'EXIT', {badarith, _}} = (catch bnot A). + + + +stacktrace(Conf) when is_list(Conf) -> + Tag = make_ref(), + ?line {_,Mref} = spawn_monitor(fun() -> exit({Tag,erlang:get_stacktrace()}) end), + ?line {Tag,[]} = receive {'DOWN',Mref,_,_,Info} -> Info end, + V = [make_ref()|self()], + ?line {value2,{caught1,badarg,[{erlang,abs,[V]}|_]=St1}} = + stacktrace_1({'abs',V}, error, {value,V}), + ?line St1 = erase(stacktrace1), + ?line St1 = erase(stacktrace2), + ?line St1 = erlang:get_stacktrace(), + ?line {caught2,{error,badarith},[{?MODULE,my_add,2}|_]=St2} = + stacktrace_1({'div',{1,0}}, error, {'add',{0,a}}), + ?line [{?MODULE,my_div,2}|_] = erase(stacktrace1), + ?line St2 = erase(stacktrace2), + ?line St2 = erlang:get_stacktrace(), + ?line {caught2,{error,{try_clause,V}},[{?MODULE,stacktrace_1,3}|_]=St3} = + stacktrace_1({value,V}, error, {value,V}), + ?line St3 = erase(stacktrace1), + ?line St3 = erase(stacktrace2), + ?line St3 = erlang:get_stacktrace(), + ?line {caught2,{throw,V},[{?MODULE,foo,1}|_]=St4} = + stacktrace_1({value,V}, error, {throw,V}), + ?line [{?MODULE,stacktrace_1,3}|_] = erase(stacktrace1), + ?line St4 = erase(stacktrace2), + ?line St4 = erlang:get_stacktrace(), + ok. + +stacktrace_1(X, C1, Y) -> + erase(stacktrace1), + erase(stacktrace2), + try try foo(X) of + C1 -> value1 + catch + C1:D1 -> {caught1,D1,erlang:get_stacktrace()} + after + put(stacktrace1, erlang:get_stacktrace()), + foo(Y) + end of + V2 -> {value2,V2} + catch + C2:D2 -> {caught2,{C2,D2},erlang:get_stacktrace()} + after + put(stacktrace2, erlang:get_stacktrace()) + end. + + + +nested_stacktrace(Conf) when is_list(Conf) -> + V = [{make_ref()}|[self()]], + ?line value1 = + nested_stacktrace_1({{value,{V,x1}},void,{V,x1}}, + {void,void,void}), + ?line {caught1, + [{?MODULE,my_add,2}|_], + value2, + [{?MODULE,my_add,2}|_]} = + nested_stacktrace_1({{'add',{V,x1}},error,badarith}, + {{value,{V,x2}},void,{V,x2}}), + ?line {caught1, + [{?MODULE,my_add,2}|_], + {caught2,[{erlang,abs,[V]}|_]}, + [{erlang,abs,[V]}|_]} = + nested_stacktrace_1({{'add',{V,x1}},error,badarith}, + {{'abs',V},error,badarg}), + ok. + +nested_stacktrace_1({X1,C1,V1}, {X2,C2,V2}) -> + try foo(X1) of + V1 -> value1 + catch + C1:V1 -> + S1 = erlang:get_stacktrace(), + T2 = + try foo(X2) of + V2 -> value2 + catch + C2:V2 -> {caught2,erlang:get_stacktrace()} + end, + {caught1,S1,T2,erlang:get_stacktrace()} + end. + + + +raise(Conf) when is_list(Conf) -> + ?line erase(raise), + ?line A = + try + ?line try foo({'div',{1,0}}) + catch + error:badarith -> + put(raise, A0 = erlang:get_stacktrace()), + ?line erlang:raise(error, badarith, A0) + end + catch + error:badarith -> + ?line A1 = erlang:get_stacktrace(), + ?line A1 = get(raise) + end, + ?line A = erlang:get_stacktrace(), + ?line A = get(raise), + ?line [{?MODULE,my_div,2}|_] = A, + %% + N = 8, % Must be even + ?line N = erlang:system_flag(backtrace_depth, N), + ?line try even(N) + catch error:function_clause -> ok + end, + ?line B = odd_even(N, []), + ?line B = erlang:get_stacktrace(), + %% + ?line C0 = odd_even(N+1, []), + ?line C = lists:sublist(C0, N), + ?line try odd(N+1) + catch error:function_clause -> ok + end, + ?line C = erlang:get_stacktrace(), + ?line try erlang:raise(error, function_clause, C0) + catch error:function_clause -> ok + end, + ?line C = erlang:get_stacktrace(), + ok. + +odd_even(N, R) when is_integer(N), N > 1 -> + odd_even(N-1, + [if (N rem 2) == 0 -> + {?MODULE,even,1}; + true -> + {?MODULE,odd,1} + end|R]); +odd_even(1, R) -> + [{?MODULE,odd,[1]}|R]. + +even(N) when is_integer(N), N > 1, (N rem 2) == 0 -> + odd(N-1)++[N]. + +odd(N) when is_integer(N), N > 1, (N rem 2) == 1 -> + even(N-1)++[N]. + + +foo({value,Value}) -> Value; +foo({'div',{A,B}}) -> + my_div(A, B); +foo({'add',{A,B}}) -> + my_add(A, B); +foo({'abs',X}) -> + my_abs(X); +foo({error,Error}) -> + erlang:error(Error); +foo({throw,Throw}) -> + erlang:throw(Throw); +foo({exit,Exit}) -> + erlang:exit(Exit); +foo({raise,{Class,Reason,Stacktrace}}) -> + erlang:raise(Class, Reason, Stacktrace). +%%foo(function_clause) -> % must not be defined! + +my_div(A, B) -> + A div B. + +my_add(A, B) -> + A + B. + +my_abs(X) -> abs(X). + +gunilla(Config) when is_list(Config) -> + ?line {throw,kalle} = gunilla_1(), + ?line [] = erlang:get_stacktrace(), + ok. + +gunilla_1() -> + try try arne() + after + pelle + end + catch + C:R -> + {C,R} + end. + +arne() -> + %% Empty stack trace used to cause change the error class to 'error'. + erlang:raise(throw, kalle, []). + +per(Config) when is_list(Config) -> + try + t1(0,pad,0), + t2(0,pad,0) + catch + error:badarith -> + ok + end. + +t1(_,X,_) -> + (1 bsl X) + 1. + +t2(_,X,_) -> + (X bsl 1) + 1. + +%% +%% Make sure that even if a BIF builds an heap fragment, then causes an exception, +%% the stacktrace term will still be OK (specifically, that it does not contain +%% stale pointers to the arguments). +%% +exception_with_heap_frag(Config) when is_list(Config) -> + Sizes = lists:seq(0, 512), + + %% Floats are only validated when the heap fragment has been allocated. + BadFloat = <<131,99,53,46,48,$X,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,101,45,48,49,0,0,0,0,0>>, + ?line do_exception_with_heap_frag(BadFloat, Sizes), + + %% {Binary,BadFloat}: When the error in float is discovered, a refc-binary + %% has been allocated and the list of refc-binaries goes through the + %% heap fragment. + BinAndFloat = + <<131,104,2,109,0,0,1,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20, + 21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45, + 46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70, + 71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, + 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115, + 116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134, + 135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153, + 154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172, + 173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210, + 211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229, + 230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248, + 249,250,251,252,253,254,255,99,51,46,49,52,$B,$l,$u,$r,$f,48,48,48,48,48,48, + 48,48,49,50,52,51,52,101,43,48,48,0,0,0,0,0>>, + ?line do_exception_with_heap_frag(BinAndFloat, Sizes), + + %% {Fun,BadFloat} + FunAndFloat = + <<131,104,2,112,0,0,0,66,0,238,239,135,138,137,216,89,57,22,111,52,126,16,84, + 71,8,0,0,0,0,0,0,0,0,100,0,1,116,97,0,98,5,175,169,123,103,100,0,13,110,111, + 110,111,100,101,64,110,111,104,111,115,116,0,0,0,41,0,0,0,0,0,99,50,46,55,48, + $Y,57,57,57,57,57,57,57,57,57,57,57,57,57,54,52,52,55,101,43,48,48,0,0,0,0,0>>, + ?line do_exception_with_heap_frag(FunAndFloat, Sizes), + + %% [ExternalPid|BadFloat] + ExtPidAndFloat = + <<131,108,0,0,0,1,103,100,0,13,107,97,108,108,101,64,115,116,114,105,100,101, + 114,0,0,0,36,0,0,0,0,2,99,48,46,$@,48,48,48,48,48,48,48,48,48,48,48,48,48,48, + 48,48,48,48,48,101,43,48,48,0,0,0,0,0>>, + ?line do_exception_with_heap_frag(ExtPidAndFloat, Sizes), + + ok. + +do_exception_with_heap_frag(Bin, [Sz|Sizes]) -> + Filler = erlang:make_tuple(Sz, a), + spawn(fun() -> + try + binary_to_term(Bin) + catch + _:_ -> + %% term_to_binary/1 is an easy way to traverse the + %% entire stacktrace term to make sure that every part + %% of it is OK. + term_to_binary(erlang:get_stacktrace()) + end, + id(Filler) + end), + do_exception_with_heap_frag(Bin, Sizes); +do_exception_with_heap_frag(_, []) -> ok. + +id(I) -> I. diff --git a/erts/emulator/test/float_SUITE.erl b/erts/emulator/test/float_SUITE.erl new file mode 100644 index 0000000000..102e472ea6 --- /dev/null +++ b/erts/emulator/test/float_SUITE.erl @@ -0,0 +1,167 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(float_SUITE). + +-include("test_server.hrl"). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + fpe/1,fp_drv/1,fp_drv_thread/1,denormalized/1,match/1,bad_float_unpack/1]). + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog = ?t:timetrap(?t:minutes(3)), + [{watchdog, Dog},{testcase,Func}|Config]. + +fin_per_testcase(_Func, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +all(suite) -> + [fpe,fp_drv,fp_drv_thread,denormalized,match,bad_float_unpack]. + +%% Forces floating point exceptions and tests that subsequent, legal, +%% operations are calculated correctly. Original version by Sebastian +%% Strollo. + +fpe(Config) when is_list(Config) -> + ?line 0.0 = math:log(1.0), + ?line {'EXIT', {badarith, _}} = (catch math:log(-1.0)), + ?line 0.0 = math:log(1.0), + ?line {'EXIT', {badarith, _}} = (catch math:log(0.0)), + ?line 0.0 = math:log(1.0), + ?line {'EXIT',{badarith,_}} = (catch 3.23e133 * id(3.57e257)), + ?line 0.0 = math:log(1.0), + ?line {'EXIT',{badarith,_}} = (catch 5.0/id(0.0)), + ?line 0.0 = math:log(1.0), + ok. + + +-define(ERTS_FP_CONTROL_TEST, 0). +-define(ERTS_FP_THREAD_TEST, 1). + +fp_drv(Config) when is_list(Config) -> + fp_drv_test(?ERTS_FP_CONTROL_TEST, ?config(data_dir, Config)). + +fp_drv_thread(Config) when is_list(Config) -> + %% Run in a separate node since it used to crash the emulator... + ?line Parent = self(), + ?line DrvDir = ?config(data_dir, Config), + ?line {ok,Node} = start_node(Config), + ?line Tester = spawn_link(Node, + fun () -> + Parent ! + {self(), + fp_drv_test(?ERTS_FP_THREAD_TEST, + DrvDir)} + end), + ?line Result = receive {Tester, Res} -> Res end, + ?line stop_node(Node), + ?line Result. + +fp_drv_test(Test, DrvDir) -> + ?line Drv = fp_drv, + ?line try + begin + ?line case erl_ddll:load_driver(DrvDir, Drv) of + ok -> + ok; + {error, permanent} -> + ok; + {error, LoadError} -> + exit({load_error, + erl_ddll:format_error(LoadError)}); + LoadError -> + exit({load_error, LoadError}) + end, + case open_port({spawn, Drv}, []) of + Port when is_port(Port) -> + try port_control(Port, Test, "") of + "ok" -> + 0.0 = math:log(1.0), + ok; + [$s,$k,$i,$p,$:,$ | Reason] -> + {skipped, Reason}; + Error -> + exit(Error) + after + Port ! {self(), close}, + receive {Port, closed} -> ok end, + false = lists:member(Port, erlang:ports()), + ok + end; + Error -> + exit({open_port_failed, Error}) + end + end + catch + throw:Term -> ?line Term + after + erl_ddll:unload_driver(Drv) + end. + +denormalized(Config) when is_list(Config) -> + ?line Denormalized = 1.0e-307 / 1000, + ?line roundtrip(Denormalized), + ?line NegDenormalized = -1.0e-307 / 1000, + ?line roundtrip(NegDenormalized), + ok. + +roundtrip(N) -> + N = binary_to_term(term_to_binary(N)), + N = binary_to_term(term_to_binary(N, [{minor_version,1}])). + +match(Config) when is_list(Config) -> + ?line one = match_1(1.0), + ?line two = match_1(2.0), + ?line a_lot = match_1(1000.0), + ?line {'EXIT',_} = (catch match_1(0.5)), + ok. + +match_1(1.0) -> one; +match_1(2.0) -> two; +match_1(1000.0) -> a_lot. + +%% Thanks to Per Gustafsson. + +bad_float_unpack(Config) when is_list(Config) -> + ?line Bin = <<-1:64>>, + ?line -1 = bad_float_unpack_match(Bin), + ok. + +bad_float_unpack_match(<<F:64/float>>) -> F; +bad_float_unpack_match(<<I:64/integer-signed>>) -> I. + +id(I) -> I. + +start_node(Config) when is_list(Config) -> + ?line Pa = filename:dirname(code:which(?MODULE)), + ?line {A, B, C} = now(), + ?line Name = list_to_atom(atom_to_list(?MODULE) + ++ "-" + ++ atom_to_list(?config(testcase, Config)) + ++ "-" + ++ integer_to_list(A) + ++ "-" + ++ integer_to_list(B) + ++ "-" + ++ integer_to_list(C)), + ?line ?t:start_node(Name, slave, [{args, "-pa "++Pa}]). + +stop_node(Node) -> + ?t:stop_node(Node). diff --git a/erts/emulator/test/float_SUITE_data/Makefile.src b/erts/emulator/test/float_SUITE_data/Makefile.src new file mode 100644 index 0000000000..628fece803 --- /dev/null +++ b/erts/emulator/test/float_SUITE_data/Makefile.src @@ -0,0 +1,8 @@ +DRVS = fp_drv@dll@ + +all: has_fpe_bug $(DRVS) + +has_fpe_bug: + @erl_name@ -compile has_fpe_bug -s has_fpe_bug + +@SHLIB_RULES@ diff --git a/erts/emulator/test/float_SUITE_data/fp_drv.c b/erts/emulator/test/float_SUITE_data/fp_drv.c new file mode 100644 index 0000000000..eb453f6cd6 --- /dev/null +++ b/erts/emulator/test/float_SUITE_data/fp_drv.c @@ -0,0 +1,142 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson AB. Portions + * created by Ericsson are Copyright 2008, Ericsson AB. All Rights + * Reserved.'' + * + * $Id$ + */ + +#if defined(DEBUG) || 0 +# define PRINTF(X) printf X +#else +# define PRINTF(X) +#endif + +#include <math.h> +#ifdef __WIN32__ +#include <float.h> +#if defined (__GNUC__) +int _finite(double x); +#endif +#ifndef finite +#define finite _finite +#endif +#endif +#include "erl_driver.h" + +#define ERTS_FP_CONTROL_TEST 0 +#define ERTS_FP_THREAD_TEST 1 + +static int control(ErlDrvData, unsigned int, char *, int, char **, int); + +static ErlDrvEntry fp_drv_entry = { + NULL /* init */, + NULL /* start */, + NULL /* stop */, + NULL /* output */, + NULL /* ready_input */, + NULL /* ready_output */, + "fp_drv", + NULL /* finish */, + NULL /* handle */, + control, + NULL /* timeout */, + NULL /* outputv */, + NULL /* ready_async */, + NULL /* flush */, + NULL /* call */, + NULL /* event */, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + ERL_DRV_FLAG_USE_PORT_LOCKING, + NULL /* handle2 */, + NULL /* process_exit */ +}; + +DRIVER_INIT(fp_drv) +{ + return &fp_drv_entry; +} + +void * +do_test(void *unused) +{ + double x, y, z; + + x = 3.23e133; + y = 3.57e257; + z = x*y; + if (finite(z)) + return "is finite (1)"; + + x = 5.0; + y = 0.0; + z = x/y; + if (finite(z)) + return "is finite (2)"; + + z = log(-1.0); + if (finite(z)) + return "is finite (3)"; + + z = log(0.0); + if (finite(z)) + return "is finite (4)"; + + return "ok"; +} + +static int control(ErlDrvData drv_data, + unsigned int command, + char *buf, int len, + char **rbuf, int rlen) +{ + char *res_str; + PRINTF(("control(%p, %d, ...) called\r\n", drv_data, command)); + + switch (command) { + case ERTS_FP_THREAD_TEST: { + ErlDrvTid tid; + ErlDrvSysInfo info; + driver_system_info(&info, sizeof(ErlDrvSysInfo)); + if (!info.thread_support) + res_str = "skip: no thread support"; + else if (0 != erl_drv_thread_create("test", &tid, do_test, NULL, NULL)) + res_str = "failed to create thread"; + else if (0 != erl_drv_thread_join(tid, &res_str)) + res_str = "failed to join thread"; + break; + } + case ERTS_FP_CONTROL_TEST: + res_str = do_test(NULL); + break; + default: + res_str = "unknown command"; + break; + } + + done: { + int res_len = strlen(res_str); + if (res_len > rlen) { + char *abuf = driver_alloc(sizeof(char)*res_len); + if (!abuf) + return 0; + *rbuf = abuf; + } + + memcpy((void *) *rbuf, (void *) res_str, res_len); + + return res_len; + } +} diff --git a/erts/emulator/test/float_SUITE_data/has_fpe_bug.erl b/erts/emulator/test/float_SUITE_data/has_fpe_bug.erl new file mode 100644 index 0000000000..31af2b2698 --- /dev/null +++ b/erts/emulator/test/float_SUITE_data/has_fpe_bug.erl @@ -0,0 +1,31 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(has_fpe_bug). + +-export([start/0]). + +start() -> + case catch math:log(-1.0) of + {'EXIT', {badarith, _}} -> + halt(0); % Ok. + _ -> + file:write_file(skip_reason, "Known FPE bug"), + halt(1) + end. diff --git a/erts/emulator/test/fun_SUITE.erl b/erts/emulator/test/fun_SUITE.erl new file mode 100644 index 0000000000..716ee3707d --- /dev/null +++ b/erts/emulator/test/fun_SUITE.erl @@ -0,0 +1,884 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(fun_SUITE). +-compile({nowarn_deprecated_function, {erlang,hash,2}}). + +-define(default_timeout, ?t:minutes(1)). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + bad_apply/1,bad_fun_call/1,badarity/1,ext_badarity/1, + equality/1,ordering/1, + fun_to_port/1,t_hash/1,t_phash/1,t_phash2/1,md5/1, + refc/1,refc_ets/1,refc_dist/1, + const_propagation/1,t_arity/1,t_is_function2/1, + t_fun_info/1]). + +-export([nothing/0]). + +-include("test_server.hrl"). + +all(suite) -> + [bad_apply,bad_fun_call,badarity,ext_badarity,equality,ordering, + fun_to_port,t_hash,t_phash,t_phash2,md5, + refc,refc_ets,refc_dist,const_propagation, + t_arity,t_is_function2,t_fun_info]. + +init_per_testcase(_Case, Config) -> + ?line Dog = test_server:timetrap(?default_timeout), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +bad_apply(doc) -> + "Test that the correct EXIT code is returned for all types of bad funs."; +bad_apply(suite) -> []; +bad_apply(Config) when is_list(Config) -> + ?line bad_apply_fc(42, [0]), + ?line bad_apply_fc(xx, [1]), + ?line bad_apply_fc({}, [2]), + ?line bad_apply_fc({1}, [3]), + ?line bad_apply_fc({1,2,3}, [4]), + ?line bad_apply_fc({1,2,3}, [5]), + ?line bad_apply_fc({1,2,3,4}, [6]), + ?line bad_apply_fc({1,2,3,4,5,6}, [7]), + ?line bad_apply_fc({1,2,3,4,5}, [8]), + ?line bad_apply_badarg({1,2}, [9]), + ok. + +bad_apply_fc(Fun, Args) -> + Res = (catch apply(Fun, Args)), + erlang:garbage_collect(), + erlang:yield(), + case Res of + {'EXIT',{{badfun,Fun},_Where}} -> + ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res]); + Other -> + ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res]), + ?t:fail({bad_result,Other}) + end. + +bad_apply_badarg(Fun, Args) -> + Res = (catch apply(Fun, Args)), + erlang:garbage_collect(), + erlang:yield(), + case Res of + {'EXIT',{{badfun,Fun},_Where}} -> + ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res]); + Other -> + ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res]), + ?t:fail({bad_result, Other}) + end. + +bad_fun_call(doc) -> + "Try directly calling bad funs."; +bad_fun_call(suite) -> []; +bad_fun_call(Config) when is_list(Config) -> + ?line bad_call_fc(42), + ?line bad_call_fc(xx), + ?line bad_call_fc({}), + ?line bad_call_fc({1}), + ?line bad_call_fc({1,2,3}), + ?line bad_call_fc({1,2,3}), + ?line bad_call_fc({1,2,3,4}), + ?line bad_call_fc({1,2,3,4,5,6}), + ?line bad_call_fc({1,2,3,4,5}), + ?line bad_call_fc({1,2}), + ok. + +bad_call_fc(Fun) -> + Args = [some,stupid,args], + Res = (catch Fun(Fun(Args))), + case Res of + {'EXIT',{{badfun,Fun},_Where}} -> + ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]); + Other -> + ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]), + ?t:fail({bad_result,Other}) + end. + +%% Call and apply valid funs with wrong number of arguments. + +badarity(Config) when is_list(Config) -> + ?line Fun = fun() -> ok end, + ?line Stupid = {stupid,arguments}, + ?line Args = [some,{stupid,arguments},here], + + %% Simple call. + + ?line Res = (catch Fun(some, Stupid, here)), + erlang:garbage_collect(), + erlang:yield(), + case Res of + {'EXIT',{{badarity,{Fun,Args}},_}} -> + ?line ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]); + _ -> + ?line ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]), + ?line ?t:fail({bad_result,Res}) + end, + + %% Apply. + + ?line Res2 = (catch apply(Fun, Args)), + erlang:garbage_collect(), + erlang:yield(), + case Res2 of + {'EXIT',{{badarity,{Fun,Args}},_}} -> + ?line ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]); + _ -> + ?line ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]), + ?line ?t:fail({bad_result,Res2}) + end, + ok. + +%% Call and apply valid external funs with wrong number of arguments. + +ext_badarity(Config) when is_list(Config) -> + ?line Fun = fun ?MODULE:nothing/0, + ?line Stupid = {stupid,arguments}, + ?line Args = [some,{stupid,arguments},here], + + %% Simple call. + + ?line Res = (catch Fun(some, Stupid, here)), + erlang:garbage_collect(), + erlang:yield(), + case Res of + {'EXIT',{{badarity,{Fun,Args}},_}} -> + ?line ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]); + _ -> + ?line ok = io:format("~p(~p) -> ~p\n", [Fun,Args,Res]), + ?line ?t:fail({bad_result,Res}) + end, + + %% Apply. + + ?line Res2 = (catch apply(Fun, Args)), + erlang:garbage_collect(), + erlang:yield(), + case Res2 of + {'EXIT',{{badarity,{Fun,Args}},_}} -> + ?line ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]); + _ -> + ?line ok = io:format("apply(~p, ~p) -> ~p\n", [Fun,Args,Res2]), + ?line ?t:fail({bad_result,Res2}) + end, + ok. + +nothing() -> + ok. + +%% Test equality of funs. + +equality(Config) when is_list(Config) -> + F0 = fun() -> 1 end, + F0_copy = copy_term(F0), + ?line true = eq(F0, F0), + ?line true = eq(F0, F0_copy), + + %% Compare different arities. + F1 = fun(X) -> X + 1 end, + ?line true = eq(F1, F1), + ?line false = eq(F0, F1), + ?line false = eq(F0_copy, F1), + + %% Compare different environments. + G1 = make_fun(1), + G2 = make_fun(2), + ?line true = eq(G1, G1), + ?line true = eq(G2, G2), + ?line false = eq(G1, G2), + ?line false = eq(G2, G1), + G1_copy = copy_term(G1), + ?line true = eq(G1, G1_copy), + + %% Compare fun with binaries. + B = list_to_binary([7,8,9]), + ?line false = eq(B, G1), + ?line false = eq(G1, B), + + %% Compare external funs. + FF0 = fun aa:blurf/0, + FF0_copy = copy_term(FF0), + FF1 = fun erlang:abs/0, + FF2 = fun erlang:exit/1, + FF3 = fun erlang:exit/2, + FF4 = fun z:ff/0, + + ?line true = eq(FF0, FF0), + ?line true = eq(FF0, FF0_copy), + ?line true = eq(FF1, FF1), + ?line true = eq(FF2, FF2), + ?line true = eq(FF3, FF3), + ?line true = eq(FF4, FF4), + ?line false = eq(FF0, FF1), + ?line false = eq(FF0, FF2), + ?line false = eq(FF0, FF3), + ?line false = eq(FF0, FF4), + ?line false = eq(FF1, FF0), + ?line false = eq(FF1, FF2), + ?line false = eq(FF1, FF3), + ?line false = eq(FF1, FF4), + ?line false = eq(FF2, FF3), + ?line false = eq(FF2, FF4), + ?line false = eq(FF3, FF4), + + ok. + +eq(X, X) -> true; +eq(_, _) -> false. + +copy_term(Term) -> + binary_to_term(term_to_binary(Term)). + +make_fun(X) -> + fun() -> X end. + +ordering(doc) -> "Tests ordering of funs."; +ordering(Config) when is_list(Config) -> + F1 = make_fun(1, 2), + F1_copy = copy_term(F1), + F2 = make_fun(1, 3), + F3 = make_fun(3, 4), + + FF0 = fun aa:blurf/0, + FF1 = fun erlang:abs/0, + FF2 = fun erlang:exit/1, + FF3 = fun erlang:exit/2, + FF4 = fun z:ff/0, + + ?line true = FF0 < FF1, + ?line true = FF1 < FF2, + ?line true = FF2 < FF3, + ?line true = FF3 < FF4, + + ?line true = FF0 > F1, + ?line true = FF0 > F2, + ?line true = FF0 > F3, + ?line true = FF4 > F1, + ?line true = FF4 > F2, + ?line true = FF4 > F3, + + ?line true = F1 == F1, + ?line true = F1 == F1_copy, + ?line true = F1 /= F2, + + ?line true = F1 < F2, + ?line true = F2 > F1, + ?line true = F2 < F3, + ?line true = F3 > F2, + + ?line false = F1 > F2, + ?line false = F2 > F3, + + %% Compare with binaries. + + B = list_to_binary([7,8,9,10]), + ?line false = B == F1, + ?line false = F1 == B, + + ?line true = F1 < B, + ?line true = B > F2, + + ?line false = F1 > B, + ?line false = B < F2, + + ?line false = F1 >= B, + ?line false = B =< F2, + + %% Compare module funs with binaries. + ?line false = B == FF1, + ?line false = FF1 == B, + + ?line true = FF1 < B, + ?line true = B > FF2, + + ?line false = FF1 > B, + ?line false = B < FF2, + + ?line false = FF1 >= B, + ?line false = B =< FF2, + + %% Create a port and ref. + + ?line Path = ?config(priv_dir, Config), + ?line AFile = filename:join(Path, "vanilla_file"), + ?line P = open_port(AFile, [out]), + ?line R = make_ref(), + + %% Compare funs with ports and refs. + + ?line true = R < F3, + ?line true = F3 > R, + ?line true = F3 < P, + ?line true = P > F3, + + ?line true = R =< F3, + ?line true = F3 >= R, + ?line true = F3 =< P, + ?line true = P >= F3, + + ?line false = R > F3, + ?line false = F3 < R, + ?line false = F3 > P, + ?line false = P < F3, + + %% Compare funs with conses and nils. + + ?line true = F1 < [a], + ?line true = F1 < [], + ?line true = [a,b] > F1, + ?line true = [] > F1, + + ?line false = [1] < F1, + ?line false = [] < F1, + ?line false = F1 > [2], + ?line false = F1 > [], + + ?line false = [1] =< F1, + ?line false = [] =< F1, + ?line false = F1 >= [2], + ?line false = F1 >= [], + + %% Compare module funs with conses and nils. + + ?line true = FF1 < [a], + ?line true = FF1 < [], + ?line true = [a,b] > FF1, + ?line true = [] > FF1, + + ?line false = [1] < FF1, + ?line false = [] < FF1, + ?line false = FF1 > [2], + ?line false = FF1 > [], + + ?line false = [1] =< FF1, + ?line false = [] =< FF1, + ?line false = FF1 >= [2], + ?line false = FF1 >= [], + ok. + +make_fun(X, Y) -> + fun(A) -> A*X+Y end. + +fun_to_port(doc) -> "Try sending funs to ports (should fail)."; +fun_to_port(suite) -> []; +fun_to_port(Config) when is_list(Config) -> + ?line fun_to_port(Config, xxx), + ?line fun_to_port(Config, fun() -> 42 end), + ?line fun_to_port(Config, [fun() -> 43 end]), + ?line fun_to_port(Config, [1,fun() -> 44 end]), + ?line fun_to_port(Config, [0,1|fun() -> 45 end]), + B64K = build_io_list(65536), + ?line fun_to_port(Config, [B64K,fun() -> 45 end]), + ?line fun_to_port(Config, [B64K|fun() -> 45 end]), + ok. + +fun_to_port(Config, IoList) -> + Path = ?config(priv_dir, Config), + AFile = filename:join(Path, "vanilla_file"), + Port = open_port(AFile, [out]), + case catch port_command(Port, IoList) of + {'EXIT',{badarg,_}} -> ok; + Other -> ?t:fail({unexpected_retval,Other}) + end. + +build_io_list(0) -> []; +build_io_list(1) -> [7]; +build_io_list(N) -> + L = build_io_list(N div 2), + case N rem 2 of + 0 -> [L|L]; + 1 -> [7,L|L] + end. + +t_hash(doc) -> "Test the hash/2 BIF on funs."; +t_hash(suite) -> []; +t_hash(Config) when is_list(Config) -> + F1 = fun(_X) -> 1 end, + F2 = fun(_X) -> 2 end, + ?line true = hash(F1) /= hash(F2), + + G1 = make_fun(1, 2, 3), + G2 = make_fun(1, 2, 3), + G3 = make_fun(1, 2, 4), + ?line true = hash(G1) == hash(G2), + ?line true = hash(G2) /= hash(G3), + + FF0 = fun erlang:abs/1, + FF1 = fun erlang:exit/1, + FF2 = fun erlang:exit/2, + FF3 = fun blurf:exit/2, + ?line true = hash(FF0) =/= hash(FF1), + ?line true = hash(FF0) =/= hash(FF2), + ?line true = hash(FF0) =/= hash(FF3), + ?line true = hash(FF1) =/= hash(FF2), + ?line true = hash(FF1) =/= hash(FF3), + ?line true = hash(FF2) =/= hash(FF3), + ok. + +hash(Term) -> + erlang:hash(Term, 16#7ffffff). + +t_phash(doc) -> "Test the phash/2 BIF on funs."; +t_phash(suite) -> []; +t_phash(Config) when is_list(Config) -> + F1 = fun(_X) -> 1 end, + F2 = fun(_X) -> 2 end, + ?line true = phash(F1) /= phash(F2), + + G1 = make_fun(1, 2, 3), + G2 = make_fun(1, 2, 3), + G3 = make_fun(1, 2, 4), + ?line true = phash(G1) == phash(G2), + ?line true = phash(G2) /= phash(G3), + + FF0 = fun erlang:abs/1, + FF1 = fun erlang:exit/1, + FF2 = fun erlang:exit/2, + FF3 = fun blurf:exit/2, + ?line true = phash(FF0) =/= phash(FF1), + ?line true = phash(FF0) =/= phash(FF2), + ?line true = phash(FF0) =/= phash(FF3), + ?line true = phash(FF1) =/= phash(FF2), + ?line true = phash(FF1) =/= phash(FF3), + ?line true = phash(FF2) =/= phash(FF3), + + ok. + +phash(Term) -> + erlang:phash(Term, 16#7ffffff). + +t_phash2(doc) -> "Test the phash2/2 BIF on funs."; +t_phash2(suite) -> []; +t_phash2(Config) when is_list(Config) -> + F1 = fun(_X) -> 1 end, + F2 = fun(_X) -> 2 end, + ?line true = phash2(F1) /= phash2(F2), + + G1 = make_fun(1, 2, 3), + G2 = make_fun(1, 2, 3), + G3 = make_fun(1, 2, 4), + ?line true = phash2(G1) == phash2(G2), + ?line true = phash2(G2) /= phash2(G3), + + FF0 = fun erlang:abs/1, + FF1 = fun erlang:exit/1, + FF2 = fun erlang:exit/2, + FF3 = fun blurf:exit/2, + ?line true = phash2(FF0) =/= phash2(FF1), + ?line true = phash2(FF0) =/= phash2(FF2), + ?line true = phash2(FF0) =/= phash2(FF3), + ?line true = phash2(FF1) =/= phash2(FF2), + ?line true = phash2(FF1) =/= phash2(FF3), + ?line true = phash2(FF2) =/= phash2(FF3), + + ok. + +phash2(Term) -> + erlang:phash2(Term, 16#7ffffff). + +make_fun(X, Y, Z) -> + fun() -> {X,Y,Z} end. + +md5(doc) -> "Test that MD5 bifs reject funs properly."; +md5(suite) -> []; +md5(Config) when is_list(Config) -> + _ = size(erlang:md5_init()), + + %% Try funs in the i/o list. + ?line bad_md5(fun(_X) -> 42 end), + ?line bad_md5([fun(_X) -> 43 end]), + ?line bad_md5([1,fun(_X) -> 44 end]), + ?line bad_md5([1|fun(_X) -> 45 end]), + ?line B64K = build_io_list(65536), + ?line bad_md5([B64K,fun(_X) -> 46 end]), + ?line bad_md5([B64K|fun(_X) -> 46 end]), + ok. + +bad_md5(Bad) -> + {'EXIT',{badarg,_}} = (catch erlang:md5(Bad)). + +refc(Config) when is_list(Config) -> + case erlang:system_info(heap_type) of + private -> refc_1(); + hybrid -> {skip,"Hybrid heap"} + end. + +refc_1() -> + ?line F1 = fun_factory(2), + ?line {refc,2} = erlang:fun_info(F1, refc), + ?line F2 = fun_factory(42), + ?line {refc,3} = erlang:fun_info(F1, refc), + + ?line process_flag(trap_exit, true), + ?line Pid = spawn_link(fun() -> {refc,4} = erlang:fun_info(F1, refc) end), + receive + {'EXIT',Pid,normal} -> ok; + Other -> ?line ?t:fail({unexpected,Other}) + end, + ?line process_flag(trap_exit, false), + ?line {refc,3} = erlang:fun_info(F1, refc), + + %% Garbage collect. Only the F2 fun will be left. + ?line 7 = F1(5), + ?line true = erlang:garbage_collect(), + ?line 40 = F2(-2), + ?line {refc,2} = erlang:fun_info(F2, refc), + ok. + +fun_factory(Const) -> + fun(X) -> X + Const end. + +refc_ets(Config) when is_list(Config) -> + case erlang:system_info(heap_type) of + private -> refc_ets_1(); + hybrid -> {skip,"Hybrid heap"} + end. + +refc_ets_1() -> + ?line F = fun(X) -> X + 33 end, + ?line {refc,2} = erlang:fun_info(F, refc), + + refc_ets_set(F, [set]), + refc_ets_set(F, [ordered_set]), + refc_ets_bag(F, [bag]), + refc_ets_bag(F, [duplicate_bag]), + ok. + +refc_ets_set(F1, Options) -> + ?line io:format("~p", [Options]), + ?line Tab = ets:new(kalle, Options), + ?line true = ets:insert(Tab, {a_key,F1}), + ?line 3 = fun_refc(F1), + ?line [{a_key,F3}] = ets:lookup(Tab, a_key), + ?line 4 = fun_refc(F1), + ?line true = ets:insert(Tab, {a_key,not_a_fun}), + ?line 3 = fun_refc(F1), + ?line true = ets:insert(Tab, {another_key,F1}), + ?line 4 = fun_refc(F1), + ?line true = ets:delete(Tab), + ?line 3 = fun_refc(F1), + ?line 10 = F3(-23), + ?line true = erlang:garbage_collect(), + ?line 2 = fun_refc(F1), + ok. + +refc_ets_bag(F1, Options) -> + ?line io:format("~p", [Options]), + ?line Tab = ets:new(kalle, Options), + ?line true = ets:insert(Tab, {a_key,F1}), + ?line 3 = fun_refc(F1), + ?line [{a_key,F3}] = ets:lookup(Tab, a_key), + ?line 4 = fun_refc(F1), + ?line true = ets:insert(Tab, {a_key,not_a_fun}), + ?line 4 = fun_refc(F1), + ?line true = ets:insert(Tab, {another_key,F1}), + ?line 5 = fun_refc(F1), + ?line true = ets:delete(Tab), + ?line 3 = fun_refc(F1), + ?line 10 = F3(-23), + ?line true = erlang:garbage_collect(), + ?line 2 = fun_refc(F1), + ok. + +refc_dist(Config) when is_list(Config) -> + case erlang:system_info(heap_type) of + private -> refc_dist_1(); + hybrid -> {skip,"Hybrid heap"} + end. + +refc_dist_1() -> + ?line {ok,Node} = start_node(fun_SUITE_refc_dist), + ?line process_flag(trap_exit, true), + ?line Pid = spawn_link(Node, + fun() -> receive + Fun when is_function(Fun) -> + 2 = fun_refc(Fun), + exit({normal,Fun}) end + end), + ?line F = fun() -> 42 end, + ?line 2 = fun_refc(F), + ?line Pid ! F, + F2 = receive + {'EXIT',Pid,{normal,Fun}} -> Fun; + Other -> ?line ?t:fail({unexpected,Other}) + end, + %% dist.c:net_mess2 have a reference to Fun for a while since + %% Fun is passed in an exit signal. Wait until it is gone. + ?line wait_until(fun () -> 4 =/= fun_refc(F2) end), + ?line 3 = fun_refc(F2), + ?line 3 = fun_refc(F), + refc_dist_send(Node, F). + +refc_dist_send(Node, F) -> + ?line true = erlang:garbage_collect(), + ?line Pid = spawn_link(Node, + fun() -> receive + {To,Fun} when is_function(Fun) -> + wait_until(fun () -> + 2 =:= fun_refc(Fun) + end), + To ! Fun + end + end), + ?line 2 = fun_refc(F), + Pid ! {self(),F}, + F2 = receive + Fun when is_function(Fun) -> Fun; + Other -> ?line ?t:fail({unexpected,Other}) + end, + receive {'EXIT',Pid,normal} -> ok end, + %% No reference from dist.c:net_mess2 since Fun is passed + %% in an ordinary message. + ?line 3 = fun_refc(F), + ?line 3 = fun_refc(F2), + refc_dist_reg_send(Node, F). + +refc_dist_reg_send(Node, F) -> + ?line true = erlang:garbage_collect(), + ?line 2 = fun_refc(F), + ?line Ref = make_ref(), + ?line Me = self(), + ?line Pid = spawn_link(Node, + fun() -> + true = register(my_fun_tester, self()), + Me ! Ref, + receive + {Me,Fun} when is_function(Fun) -> + 2 = fun_refc(Fun), + Me ! Fun + end + end), + erlang:yield(), + ?line 2 = fun_refc(F), + receive Ref -> ok end, + {my_fun_tester,Node} ! {self(),F}, + F2 = receive + Fun when is_function(Fun) -> Fun; + Other -> ?line ?t:fail({unexpected,Other}) + end, + receive {'EXIT',Pid,normal} -> ok end, + + ?line 3 = fun_refc(F), + ?line 3 = fun_refc(F2), + ok. + +fun_refc(F) -> + {refc,Count} = erlang:fun_info(F, refc), + Count. + +const_propagation(Config) when is_list(Config) -> + ?line Fun1 = fun start_node/1, + ?line 2 = fun_refc(Fun1), + ?line Fun2 = Fun1, + ?line my_cmp({Fun1,Fun2}), + + ?line Fun3 = fun() -> ok end, + ?line 2 = fun_refc(Fun3), + ?line Fun4 = Fun3, + ?line my_cmp({Fun3,Fun4}), + ok. + +my_cmp({Fun,Fun}) -> ok; +my_cmp({Fun1,Fun2}) -> + io:format("Fun1: ~p", [erlang:fun_info(Fun1)]), + io:format("Fun2: ~p", [erlang:fun_info(Fun2)]), + ?t:fail(). + +t_arity(Config) when is_list(Config) -> + ?line 0 = fun_arity(fun() -> ok end), + ?line 0 = fun_arity(fun() -> Config end), + ?line 1 = fun_arity(fun(X) -> X+1 end), + ?line 1 = fun_arity(fun(X) -> Config =:= X end), + A = id(42), + + %% Test that the arity is transferred properly. + ?line process_flag(trap_exit, true), + ?line {ok,Node} = start_node(fun_test_arity), + ?line hello_world = spawn_call(Node, fun() -> hello_world end), + ?line 0 = spawn_call(Node, fun(X) -> X end), + ?line 42 = spawn_call(Node, fun(_X) -> A end), + ?line 43 = spawn_call(Node, fun(X, Y) -> A+X+Y end), + ?line 1 = spawn_call(Node, fun(X, Y) -> X+Y end), + ?line 45 = spawn_call(Node, fun(X, Y, Z) -> A+X+Y+Z end), + ok. + +t_is_function2(Config) when is_list(Config) -> + ?line true = is_function({a,b}, 0), + ?line true = is_function({a,b}, 234343434333433433), + ?line true = is_function(fun() -> ok end, 0), + ?line true = is_function(fun(_) -> ok end, 1), + ?line false = is_function(fun(_) -> ok end, 0), + + ?line true = is_function(fun erlang:abs/1, 1), + ?line true = is_function(fun erlang:abs/99, 99), + ?line false = is_function(fun erlang:abs/1, 0), + ?line false = is_function(fun erlang:abs/99, 0), + + ?line false = is_function(id(self()), 0), + ?line false = is_function(id({a,b,c}), 0), + ?line false = is_function(id({a}), 0), + ?line false = is_function(id([a,b,c]), 0), + + %% Bad arity argument. + ?line bad_arity(a), + ?line bad_arity(-1), + ?line bad_arity(-9738974938734938793873498378), + ?line bad_arity([]), + ?line bad_arity(fun() -> ok end), + ?line bad_arity({}), + ?line bad_arity({a,b}), + ?line bad_arity(self()), + ok. + +bad_arity(A) -> + {'EXIT',_} = (catch is_function(fun() -> ok end, A)), + {'EXIT',_} = (catch is_function(no_fun, A)), + ok. + +t_fun_info(Config) when is_list(Config) -> + ?line F = fun t_fun_info/1, + ?line try F(blurf) of + FAny -> + io:format("should fail; returned ~p\n", [FAny]), + ?line ?t:fail() + catch + error:function_clause -> ok + end, + ?line {module,?MODULE} = erlang:fun_info(F, module), + ?line case erlang:fun_info(F, name) of + undefined -> + ?line ?t:fail(); + _ -> ok + end, + ?line {arity,1} = erlang:fun_info(F, arity), + ?line {env,[]} = erlang:fun_info(F, env), + ?line verify_not_undef(F, index), + ?line verify_not_undef(F, uniq), + ?line verify_not_undef(F, new_index), + ?line verify_not_undef(F, new_uniq), + ?line verify_not_undef(F, refc), + ?line {'EXIT',_} = (catch erlang:fun_info(F, blurf)), + + %% Module fun. + ?line FF = fun ?MODULE:t_fun_info/1, + ?line try FF(blurf) of + FFAny -> + io:format("should fail; returned ~p\n", [FFAny]), + ?line ?t:fail() + catch + error:function_clause -> ok + end, + + ?line {module,?MODULE} = erlang:fun_info(FF, module), + ?line {name,t_fun_info} = erlang:fun_info(FF, name), + ?line {arity,1} = erlang:fun_info(FF, arity), + ?line {env,[]} = erlang:fun_info(FF, env), + ?line verify_undef(FF, index), + ?line verify_undef(FF, uniq), + ?line verify_undef(FF, new_index), + ?line verify_undef(FF, new_uniq), + ?line verify_undef(FF, refc), + ?line {'EXIT',_} = (catch erlang:fun_info(FF, blurf)), + + %% Not fun. + ?line bad_info(abc), + ?line bad_info(42), + ?line bad_info({fun erlang:list_to_integer/1}), + ?line bad_info([42]), + ?line bad_info([]), + ?line bad_info(self()), + ?line bad_info(<<>>), + ?line bad_info(<<1,2>>), + ok. + +bad_info(Term) -> + try erlang:fun_info(Term, module) of + Any -> + io:format("should fail; returned ~p\n", [Any]), + ?t:fail() + catch + error:badarg -> ok + end. + +verify_undef(Fun, Tag) -> + {Tag,undefined} = erlang:fun_info(Fun, Tag). + +verify_not_undef(Fun, Tag) -> + case erlang:fun_info(Fun, Tag) of + {Tag,undefined} -> + ?t:fail(); + {Tag,_} -> ok + end. + +id(X) -> + X. + +spawn_call(Node, AFun) -> + Pid = spawn_link(Node, + fun() -> + receive + {Fun,Fun,Fun} when is_function(Fun) -> + Arity = fun_arity(Fun), + Args = case Arity of + 0 -> []; + _ -> lists:seq(0, Arity-1) + end, + Res = apply(Fun, Args), + {pid,Creator} = erlang:fun_info(Fun, pid), + Creator ! {result,Res} + end + end), + Pid ! {AFun,AFun,AFun}, + Res = receive + {result,R} -> R; + Other -> ?t:fail({bad_message,Other}) + after 10000 -> + ?t:fail(timeout_waiting_for_result) + end, + receive + {'EXIT',Pid,normal} -> ok; + Other2 -> ?t:fail({bad_message_waiting_for_exit,Other2}) + after 10000 -> + ?t:fail(timeout_waiting_for_exit) + end, + Res. + +fun_arity(F) -> + {arity,Arity} = erlang:fun_info(F, arity), + Arity. + +start_node(Name) -> + Pa = filename:dirname(code:which(?MODULE)), + Cookie = atom_to_list(erlang:get_cookie()), + test_server:start_node(Name, slave, + [{args, "-setcookie " ++ Cookie ++" -pa " ++ Pa}]). + +wait_until(Fun) -> + case catch Fun() of + true -> ok; + _ -> receive after 100 -> wait_until(Fun) end + end. + +% stop_node(Node) -> +% test_server:stop_node(Node). diff --git a/erts/emulator/test/fun_r11_SUITE.erl b/erts/emulator/test/fun_r11_SUITE.erl new file mode 100644 index 0000000000..61ba816cc8 --- /dev/null +++ b/erts/emulator/test/fun_r11_SUITE.erl @@ -0,0 +1,76 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(fun_r11_SUITE). +-compile(r11). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2,dist_old_release/1]). + +-define(default_timeout, ?t:minutes(1)). +-include("test_server.hrl"). + +all(suite) -> [dist_old_release]. + +init_per_testcase(_Case, Config) -> + ?line Dog = test_server:timetrap(?default_timeout), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +dist_old_release(Config) when is_list(Config) -> + case ?t:is_release_available("r11b") of + true -> do_dist_old(Config); + false -> {skip,"No R11B found"} + end. + +do_dist_old(Config) when is_list(Config) -> + ?line Pa = filename:dirname(code:which(?MODULE)), + Name = fun_dist_r11, + ?line {ok,Node} = ?t:start_node(Name, peer, + [{args,"-pa "++Pa}, + {erl,[{release,"r11b"}]}]), + + ?line Pid = spawn_link(Node, + fun() -> + receive + Fun when is_function(Fun) -> + R11BFun = fun(H) -> cons(H, [b,c]) end, + Fun(Fun, R11BFun) + end + end), + Self = self(), + Fun = fun(F, R11BFun) -> + {pid,Self} = erlang:fun_info(F, pid), + {module,?MODULE} = erlang:fun_info(F, module), + Self ! {ok,F,R11BFun} + end, + ?line Pid ! Fun, + ?line receive + {ok,Fun,R11BFun} -> + ?line [a,b,c] = R11BFun(a); + Other -> + ?line ?t:fail({bad_message,Other}) + end, + ok. + +cons(H, T) -> + [H|T]. diff --git a/erts/emulator/test/gc_SUITE.erl b/erts/emulator/test/gc_SUITE.erl new file mode 100644 index 0000000000..066aa215b2 --- /dev/null +++ b/erts/emulator/test/gc_SUITE.erl @@ -0,0 +1,181 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% Test the garbage collector (or Memory Recycler) + +-module(gc_SUITE). + +-include("test_server.hrl"). +-export([all/1]). + +-define(default_timeout, ?t:minutes(10)). + +-export([grow_heap/1, grow_stack/1, grow_stack_heap/1]). + +all(suite) -> + [grow_heap,grow_stack, grow_stack_heap]. + +grow_heap(doc) -> ["Produce a growing list of elements, ", + "for X calls, then drop one item per call", + "until the list is empty."]; +grow_heap(Config) when is_list(Config) -> + ?line Dog=test_server:timetrap(test_server:minutes(40)), + ?line ok=grow_heap1(256), + case os:type() of + vxworks -> + stop_here; + _ -> + ?line ok=grow_heap1(512), + ?line ok=grow_heap1(1024), + ?line ok=grow_heap1(2048) + end, + ?line test_server:timetrap_cancel(Dog), + ok. + +grow_heap1(Len) -> + io:format("~ngrow_heap with ~p items.",[Len]), + show_heap("before:"), + grow_heap1([], Len, 0, up), + show_heap("after:"). + +grow_heap1(List, MaxLen, MaxLen, up) -> + show_heap("top:"), + grow_heap1(List, MaxLen, MaxLen-1, down); +grow_heap1(List, MaxLen, CurLen, up) -> + NewList=[make_arbit()|List], + grow_heap1(NewList, MaxLen, CurLen+1, up); +grow_heap1([], _MaxLen, _, down) -> + ok; +grow_heap1([_|List], MaxLen, CurLen, down) -> + ?line {_,_,C}=erlang:now(), + ?line Num=C rem (length(List))+1, + ?line Elem=lists:nth(Num, List), + ?line NewList=lists:delete(Elem, List), + grow_heap1(NewList, MaxLen, CurLen-1, down). + + + +grow_stack(doc) -> ["Increase and decrease stack size, and ", + "drop off some garbage from time to time."]; +grow_stack(Config) when is_list(Config) -> + ?line Dog=test_server:timetrap(test_server:minutes(80)), + show_heap("before:"), + case os:type() of + vxworks -> + ?line grow_stack1(25, 0); + _ -> + ?line grow_stack1(200, 0) + end, + show_heap("after:"), + ?line test_server:timetrap_cancel(Dog), + ok. + +grow_stack1(0, _) -> + ok; +grow_stack1(Recs, 0) -> +% show_heap("running:"), + grow_stack1(Recs-1, Recs), + grow_stack1(0,0); +grow_stack1(Recs, CurRecs) -> + grow_stack1(Recs, CurRecs-1), + make_arbit(), + grow_stack1(1,0), + ok. + + +%% Let's see how BEAM handles this one... +grow_stack_heap(doc) -> ["While growing the heap, bounces the size ", + "of the stack, and while reducing the heap", + "bounces the stack usage."]; +grow_stack_heap(Config) when is_list(Config) -> + case os:type() of + vxworks -> + {comment, "Takes too long to run on VxWorks/cpu32"}; + _ -> + ?line Dog=test_server:timetrap(test_server:minutes(40)), + ?line grow_stack_heap1(16), + ?line grow_stack_heap1(32), + ?line test_server:timetrap_cancel(Dog), + ok + end. + +grow_stack_heap1(MaxLen) -> + io:format("~ngrow_stack_heap with ~p items.",[MaxLen]), + show_heap("before:"), + grow_stack_heap1([], MaxLen, 0, up), + show_heap("after:"). + +grow_stack_heap1(List, MaxLen, MaxLen, up) -> + show_heap("top:"), + grow_stack_heap1(List, MaxLen, MaxLen-1, down); +grow_stack_heap1(List, MaxLen, CurLen, up) -> + grow_stack1(CurLen*2,0), + grow_stack_heap1([make_arbit()|List], MaxLen, CurLen+1, up), + ok; + +grow_stack_heap1([], _MaxLen, _, down) -> ok; +grow_stack_heap1([_|List], MaxLen, CurLen, down) -> + grow_stack1(CurLen*2,0), + ?line {_,_,C}=erlang:now(), + ?line Num=C rem (length(List))+1, + ?line Elem=lists:nth(Num, List), + ?line NewList=lists:delete(Elem, List), + grow_stack_heap1(NewList, MaxLen, CurLen-1, down), + ok. + + +%% Create an arbitrary element/term. +make_arbit() -> + {AA,BB,CC}=erlang:now(), + A=AA+1, B=BB+1, C=CC+1, + New = + case C rem 9 of + 0 -> make_string((B div C) +5); + 1 -> C; + 2 -> make_ref(); + 3 -> self(); + 4 -> list_to_binary(make_string((C div B) + 12)); + 5 -> (C*B)/(A+1); + 6 -> list_to_tuple(make_string((B div C) +5)); + 7 -> list_to_atom(make_string(((C div B) rem 254) + 2)); + 8 -> fun(X) -> {X,AA,make_string((B div C)+10)} end + end, + New. + +%% Create an arbitrary string of a certain length. +make_string(Length) -> + Alph="abcdefghjiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"++ + "0123456789", + make_string(Alph, Length, []). + +make_string(_, 0, Acc) -> + Acc; +make_string(Alph, Length, Acc) -> + {_,_,C}=erlang:now(), + Pos=1+(Length*C rem length(Alph)), + make_string(Alph, Length-1, + [lists:nth(Pos,Alph)|Acc]). + +show_heap(String) -> + garbage_collect(self()), + receive after 1 -> ok end, + {heap_size, HSize}=process_info(self(), heap_size), + {stack_size, SSize}=process_info(self(), stack_size), + io:format("Heap/Stack "++String++"~p/~p", [HSize, SSize]). + diff --git a/erts/emulator/test/guard_SUITE.erl b/erts/emulator/test/guard_SUITE.erl new file mode 100644 index 0000000000..23482a20d7 --- /dev/null +++ b/erts/emulator/test/guard_SUITE.erl @@ -0,0 +1,390 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(guard_SUITE). + +-export([all/1, bad_arith/1, bad_tuple/1, test_heap_guards/1, guard_bifs/1, + type_tests/1]). + +-include("test_server.hrl"). + +-export([init/3]). +-import(lists, [member/2]). + +all(suite) -> [bad_arith, bad_tuple, test_heap_guards, guard_bifs, type_tests]. + +bad_arith(doc) -> "Test that a bad arithmetic operation in a guard works correctly."; +bad_arith(Config) when is_list(Config) -> + ?line 5 = bad_arith1(2, 3), + ?line 10 = bad_arith1(1, infinity), + ?line 10 = bad_arith1(infinity, 1), + ok. + +bad_arith1(T1, T2) when T1+T2 < 10 -> + T1+T2; +bad_arith1(_, _) -> + 10. + +bad_tuple(doc) -> "Test that bad arguments to element/2 are handled correctly."; +bad_tuple(Config) when is_list(Config) -> + ?line error = bad_tuple1(a), + ?line error = bad_tuple1({a, b}), + ?line x = bad_tuple1({x, b}), + ?line y = bad_tuple1({a, b, y}), + ok. + +bad_tuple1(T) when element(1, T) == x -> + x; +bad_tuple1(T) when element(3, T) == y -> + y; +bad_tuple1(_) -> + error. + +test_heap_guards(doc) -> ""; +test_heap_guards(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(2)), + + ?line process_flag(trap_exit, true), + ?line Tuple = {a, tuple, is, built, here, xxx}, + ?line List = [a, list, is, built, here], + + ?line 'try'(fun a_case/1, [Tuple], [Tuple]), + ?line 'try'(fun a_case/1, [List], [List, List]), + ?line 'try'(fun a_case/1, [a], [a]), + + ?line 'try'(fun an_if/1, [Tuple], [Tuple]), + ?line 'try'(fun an_if/1, [List], [List, List]), + ?line 'try'(fun an_if/1, [a], [a]), + + ?line 'try'(fun receive_test/1, [Tuple], [Tuple]), + ?line 'try'(fun receive_test/1, [List], [List, List]), + ?line 'try'(fun receive_test/1, [a], [a]), + ?line test_server:timetrap_cancel(Dog). + +a_case(V) -> + case V of + T when T == {a, tuple, is, built, here, xxx} -> + [T]; + L when L == [a, list, is, built, here] -> + [L, L]; + a -> + [a] + end. + +an_if(V) -> + if + V == {a, tuple, is, built, here, xxx} -> + [V]; + V == [a, list, is, built, here] -> + [V, V]; + V == a -> + [a] + end. + +receive_test(V) -> + self() ! V, + a_receive(). + +a_receive() -> + receive + T when T == {a, tuple, is, built, here, xxx} -> + [T]; + L when L == [a, list, is, built, here] -> + [L, L]; + a -> + [a] + end. + +'try'(Fun, Args, Result) -> + 'try'(512, Fun, Args, Result, []). + +'try'(0, _, _, _, _) -> + ok; +'try'(Iter, Fun, Args, Result, Filler) -> + Pid = spawn_link(?MODULE, init, [Fun,Args,list_to_tuple(Filler)]), + receive + {'EXIT', Pid, {result, Result}} -> + ?line 'try'(Iter-1, Fun, Args, Result, [0|Filler]); + {result, Other} -> + ?line io:format("Expected ~p; got ~p~n", [Result, Other]), + ?line test_server:fail(); + Other -> + ?line test_server:fail({unexpected_message, Other}) + end. + +init(Fun, Args, Filler) -> + Result = {result,apply(Fun, Args)}, + dummy(Filler), + exit(Result). + +dummy(_) -> + ok. + +guard_bifs(doc) -> "Test all guard bifs with nasty (but legal arguments)."; +guard_bifs(Config) when is_list(Config) -> + ?line Big = -237849247829874297658726487367328971246284736473821617265433, + ?line Float = 387924.874, + + %% Succeding use of guard bifs. + + ?line try_gbif('abs/1', Big, -Big), + ?line try_gbif('float/1', Big, float(Big)), + ?line try_gbif('float/1', Big, float(id(Big))), + ?line try_gbif('trunc/1', Float, 387924.0), + ?line try_gbif('round/1', Float, 387925.0), + ?line try_gbif('length/1', [], 0), + + ?line try_gbif('length/1', [a], 1), + ?line try_gbif('length/1', [a, b], 2), + ?line try_gbif('length/1', lists:seq(0, 31), 32), + + ?line try_gbif('hd/1', [a], a), + ?line try_gbif('hd/1', [a, b], a), + + ?line try_gbif('tl/1', [a], []), + ?line try_gbif('tl/1', [a, b], [b]), + ?line try_gbif('tl/1', [a, b, c], [b, c]), + + ?line try_gbif('size/1', {}, 0), + ?line try_gbif('size/1', {a}, 1), + ?line try_gbif('size/1', {a, b}, 2), + ?line try_gbif('size/1', {a, b, c}, 3), + ?line try_gbif('size/1', list_to_binary([]), 0), + ?line try_gbif('size/1', list_to_binary([1]), 1), + ?line try_gbif('size/1', list_to_binary([1, 2]), 2), + ?line try_gbif('size/1', list_to_binary([1, 2, 3]), 3), + + ?line try_gbif('bit_size/1', <<0:7>>, 7), + + ?line try_gbif('element/2', {x}, {1, x}), + ?line try_gbif('element/2', {x, y}, {1, x}), + ?line try_gbif('element/2', {x, y}, {2, y}), + + ?line try_gbif('self/0', 0, self()), + ?line try_gbif('node/0', 0, node()), + ?line try_gbif('node/1', self(), node()), + + %% Failing use of guard bifs. + + ?line try_fail_gbif('abs/1', Big, 1), + ?line try_fail_gbif('abs/1', [], 1), + + ?line try_fail_gbif('float/1', Big, 42), + ?line try_fail_gbif('float/1', [], 42), + + ?line try_fail_gbif('trunc/1', Float, 0.0), + ?line try_fail_gbif('trunc/1', [], 0.0), + + ?line try_fail_gbif('round/1', Float, 1.0), + ?line try_fail_gbif('round/1', [], a), + + ?line try_fail_gbif('length/1', [], 1), + ?line try_fail_gbif('length/1', [a], 0), + ?line try_fail_gbif('length/1', a, 0), + ?line try_fail_gbif('length/1', {a}, 0), + + ?line try_fail_gbif('hd/1', [], 0), + ?line try_fail_gbif('hd/1', [a], x), + ?line try_fail_gbif('hd/1', x, x), + + ?line try_fail_gbif('tl/1', [], 0), + ?line try_fail_gbif('tl/1', [a], x), + ?line try_fail_gbif('tl/1', x, x), + + ?line try_fail_gbif('size/1', {}, 1), + ?line try_fail_gbif('size/1', [], 0), + ?line try_fail_gbif('size/1', [a], 1), + ?line try_fail_gbif('size/1', fun() -> 1 end, 0), + ?line try_fail_gbif('size/1', fun() -> 1 end, 1), + + ?line try_fail_gbif('element/2', {}, {1, x}), + ?line try_fail_gbif('element/2', {x}, {1, y}), + ?line try_fail_gbif('element/2', [], {1, z}), + + ?line try_fail_gbif('self/0', 0, list_to_pid("<0.0.0>")), + ?line try_fail_gbif('node/0', 0, xxxx), + ?line try_fail_gbif('node/1', self(), xxx), + ?line try_fail_gbif('node/1', yyy, xxx), + ok. + +try_gbif(Id, X, Y) -> + case guard_bif(Id, X, Y) of + {Id, X, Y} -> + io:format("guard_bif(~p, ~p, ~p) -- ok", [Id, X, Y]); + Other -> + ?line ok = io:format("guard_bif(~p, ~p, ~p) -- bad result: ~p\n", + [Id, X, Y, Other]), + ?line test_server:fail() + end. + +try_fail_gbif(Id, X, Y) -> + case catch guard_bif(Id, X, Y) of + {'EXIT', {function_clause,[{?MODULE,guard_bif,[Id,X,Y]}|_]}} -> + io:format("guard_bif(~p, ~p, ~p) -- ok", [Id,X,Y]); + Other -> + ?line ok = io:format("guard_bif(~p, ~p, ~p) -- bad result: ~p\n", + [Id, X, Y, Other]), + ?line test_server:fail() + end. + +guard_bif('abs/1', X, Y) when abs(X) == Y -> + {'abs/1', X, Y}; +guard_bif('float/1', X, Y) when float(X) == Y -> + {'float/1', X, Y}; +guard_bif('trunc/1', X, Y) when trunc(X) == Y -> + {'trunc/1', X, Y}; +guard_bif('round/1', X, Y) when round(X) == Y -> + {'round/1', X, Y}; +guard_bif('length/1', X, Y) when length(X) == Y -> + {'length/1', X, Y}; +guard_bif('hd/1', X, Y) when hd(X) == Y -> + {'hd/1', X, Y}; +guard_bif('tl/1', X, Y) when tl(X) == Y -> + {'tl/1', X, Y}; +guard_bif('size/1', X, Y) when size(X) == Y -> + {'size/1', X, Y}; +guard_bif('bit_size/1', X, Y) when bit_size(X) == Y -> + {'bit_size/1', X, Y}; +guard_bif('element/2', X, {Pos, Expected}) when element(Pos, X) == Expected -> + {'element/2', X, {Pos, Expected}}; +guard_bif('self/0', X, Y) when self() == Y -> + {'self/0', X, Y}; +guard_bif('node/0', X, Y) when node() == Y -> + {'node/0', X, Y}; +guard_bif('node/1', X, Y) when node(X) == Y -> + {'node/1', X, Y}. + +type_tests(doc) -> "Test the type tests."; +type_tests(Config) when is_list(Config) -> + ?line Types = all_types(), + ?line Tests = type_test_desc(), + ?line put(errors, 0), + ?line put(violations, 0), + ?line type_tests(Tests, Types), + ?line case {get(errors), get(violations)} of + {0, 0} -> + ok; + {0, N} -> + {comment, integer_to_list(N) ++ " standard violation(s)"}; + {Errors, Violations} -> + io:format("~p sub test(s) failed, ~p violation(s)", + [Errors, Violations]), + ?line test_server:fail() + end. + +type_tests([{Test, AllowedTypes}| T], AllTypes) -> + type_tests(Test, AllTypes, AllowedTypes), + type_tests(T, AllTypes); +type_tests([], _) -> + ok. + +type_tests(Test, [Type|T], Allowed) -> + {TypeTag, Value} = Type, + case member(TypeTag, Allowed) of + true -> + case catch type_test(Test, Value) of + Test -> + ok; + _Other -> + io:format("Test ~p(~p) failed", [Test, Value]), + put(errors, get(errors) + 1) + end; + false -> + case catch type_test(Test, Value) of + {'EXIT', {function_clause, {?MODULE,type_test,[Test,Value]}}} -> + ok; + {'EXIT', {function_clause,[{?MODULE,type_test,[Test,Value]}|_]}} -> + ok; + {'EXIT',Other} -> + ?line test_server:fail({unexpected_error_reason,Other}); + tuple when is_function(Value) -> + io:format("Standard violation: Test ~p(~p) should fail", + [Test, Value]), + put(violations, get(violations) + 1); + _Other -> + io:format("Test ~p(~p) succeeded (should fail)", [Test, Value]), + put(errors, get(errors) + 1) + end + end, + type_tests(Test, T, Allowed); +type_tests(_, [], _) -> + ok. + +all_types() -> + [{small, 42}, + {big, 392742928742947293873938792874019287447829874290742}, + {float, 3.14156}, + {nil, []}, + {cons, [a]}, + {tuple, {a, b}}, + {atom, xxxx}, + {ref, make_ref()}, + {pid, self()}, + {port, open_port({spawn, efile}, [])}, + {function, fun(_) -> "" end}, + {function, fun erlang:abs/1}, + {binary, list_to_binary([])}, + {bitstring, <<0:7>>}]. + +type_test_desc() -> + [{binary, [binary]}, + {bitstring, [binary, bitstring]}, + {integer, [small, big]}, + {float, [float]}, + {number, [small, big, float]}, + {atom, [atom]}, + {list, [cons, nil]}, + {nonempty_list, [cons]}, + {nil, [nil]}, + {tuple, [tuple]}, + {pid, [pid]}, + {port, [port]}, + {reference, [ref]}, + {function, [function]}]. + +type_test(integer, X) when is_integer(X) -> + integer; +type_test(float, X) when is_float(X) -> + float; +type_test(number, X) when is_number(X) -> + number; +type_test(atom, X) when is_atom(X) -> + atom; +type_test(list, X) when is_list(X) -> + list; +type_test(nonempty_list, [_]) -> + nonempty_list; +type_test(nil, []) -> + nil; +type_test(tuple, X) when is_tuple(X) -> + tuple; +type_test(pid, X) when is_pid(X) -> + pid; +type_test(reference, X) when is_reference(X) -> + reference; +type_test(port, X) when is_port(X) -> + port; +type_test(binary, X) when is_binary(X) -> + binary; +type_test(bitstring, X) when is_bitstring(X) -> + bitstring; +type_test(function, X) when is_function(X) -> + function. + +id(I) -> I. diff --git a/erts/emulator/test/hash_SUITE.erl b/erts/emulator/test/hash_SUITE.erl new file mode 100644 index 0000000000..85bdb8bff8 --- /dev/null +++ b/erts/emulator/test/hash_SUITE.erl @@ -0,0 +1,717 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%% Verifying erlang:phash/2. And now also phash2/2, to some extent. +%% Test the hashing algorithm for integer numbers in 2 ways: +%% 1 Test that numbers in diferent sequences get sufficiently spread +%% in a "bit pattern" way (modulo 256 etc). +%% 2 Test that numbers are correctly hashed compared to a reference implementation, +%% regardless of their internal representation. The hashing algorithm should never +%% change. +%% The hashing of other datatypes is tested with a few samples, so that we are sure +%% it does not change across versions. +%% Also tests that the limit can be between 0 and 16#FFFFFFFF. +%% +-module(hash_SUITE). +-export([basic_test/0,cmp_test/1,range_test/0,spread_test/1, + phash2_test/0, otp_5292_test/0, bit_level_binaries/0, + otp_7127_test/0]). +-compile({nowarn_deprecated_function, {erlang,hash,2}}). + +%% +%% Define to run outside of test server +%% +%-define(STANDALONE,1). + +%% +%% Define for debug output +%% +%-define(debug,1). + +-ifdef(STANDALONE). +-define(config(A,B),config(A,B)). +-export([config/2]). +-else. +-include("test_server.hrl"). +-endif. + +-ifdef(debug). +-ifdef(STANDALONE). +-define(line, erlang:display({?MODULE,?LINE}), ). +-endif. +-define(dbgformat(A,B),io:format(A,B)). +-else. +-ifdef(STANDALONE). +-define(line, noop, ). +-endif. +-define(dbgformat(A,B),noop). +-endif. + +-ifdef(STANDALONE). +config(priv_dir,_) -> + ".". +-else. +%% When run in test server. +-export([all/1,test_basic/1,test_cmp/1,test_range/1,test_spread/1, + test_phash2/1,otp_5292/1,bit_level_binaries/1,otp_7127/1, + fin_per_testcase/2,init_per_testcase/2]). +init_per_testcase(_Case, Config) -> + ?line Dog=test_server:timetrap(test_server:minutes(10)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. +all(doc) -> + ["Test erlang:phash"]; +all(suite) -> + [test_basic, test_cmp, test_range, test_spread, test_phash2, otp_5292, + bit_level_binaries, otp_7127]. + +test_basic(suite) -> + []; +test_basic(doc) -> + ["Tests basic functionality of erlang:phash and that the " + "hashes has not changed (neither hash nor phash)"]; +test_basic(Config) when is_list(Config) -> + basic_test(). + + +test_cmp(suite) -> + []; +test_cmp(doc) -> + ["Compares integer hashes made by erlang:phash with those of a reference " + "implementation"]; +test_cmp(Config) when is_list(Config) -> + cmp_test(10000). + +test_range(suite) -> + []; +test_range(doc) -> + ["Tests ranges on erlang:phash from 1 to 2^32"]; +test_range(Config) when is_list(Config) -> + range_test(). + +test_spread(suite) -> + []; +test_spread(doc) -> + ["Tests that the hashes are spread ok"]; +test_spread(Config) when is_list(Config) -> + spread_test(10). + +test_phash2(suite) -> + []; +test_phash2(doc) -> + ["Tests phash2"]; +test_phash2(Config) when is_list(Config) -> + phash2_test(). + +otp_5292(suite) -> + []; +otp_5292(doc) -> + ["Tests hash, phash and phash2 regarding integers."]; +otp_5292(Config) when is_list(Config) -> + otp_5292_test(). + +%% Test hashing bit-level binaries. +bit_level_binaries(Config) when is_list(Config) -> + bit_level_binaries(). + +otp_7127(suite) -> + []; +otp_7127(doc) -> + ["Tests phash2/1."]; +otp_7127(Config) when is_list(Config) -> + otp_7127_test(). + +-endif. + + + +%% +%% Here are the real tests, they can be run without test_server, +%% define -DSTANDALONE when compiling. +%% +basic_test() -> + ?line 685556714 = erlang:phash({a,b,c},16#FFFFFFFF), + ?line 14468079 = erlang:hash({a,b,c},16#7FFFFFF), + ?line 37442646 = erlang:phash([a,b,c,{1,2,3},c:pid(0,2,3), + 16#77777777777777],16#FFFFFFFF), + ?line Comment = case erlang:hash([a,b,c,{1,2,3},c:pid(0,2,3), + 16#77777777777777],16#7FFFFFF) of + 102727602 -> + ?line big = erlang:system_info(endian), + "Big endian machine"; + 105818829 -> + ?line little = erlang:system_info(endian), + "Little endian machine" + end, + ExternalReference = <<131,114,0,3,100,0,13,110,111,110,111,100,101,64, + 110,111,104,111,115,116,0,0,0,0,122,0,0,0,0,0,0,0,0>>, + ?line 1113403635 = erlang:phash(binary_to_term(ExternalReference), + 16#FFFFFFFF), + ?line 123 = erlang:hash(binary_to_term(ExternalReference), + 16#7FFFFFF), + ExternalFun = <<131,117,0,0,0,3,103,100,0,13,110,111,110,111,100,101,64, + 110,111,104,111,115,116,0,0,0,38,0,0,0,0,0,100,0,8,101, + 114,108,95,101,118,97,108,97,20,98,5,182,139,98,108,0,0, + 0,3,104,2,100,0,1,66,109,0,0,0,33,131,114,0,3,100,0,13, + 110,111,110,111,100,101,64,110,111,104,111,115,116,0,0, + 0,0,122,0,0,0,0,0,0,0,0,104,2,100,0,1,76,107,0,33,131, + 114,0,3,100,0,13,110,111,110,111,100,101,64,110,111,104, + 111,115,116,0,0,0,0,122,0,0,0,0,0,0,0,0,104,2,100,0,1,82, + 114,0,3,100,0,13,110,111,110,111,100,101,64,110,111,104, + 111,115,116,0,0,0,0,122,0,0,0,0,0,0,0,0,106,108,0,0,0,1, + 104,5,100,0,6,99,108,97,117,115,101,97,1,106,106,108,0,0, + 0,1,104,3,100,0,7,105,110,116,101,103,101,114,97,1,97,1, + 106,106,104,3,100,0,4,101,118,97,108,104,2,100,0,5,115, + 104,101,108,108,100,0,10,108,111,99,97,108,95,102,117, + 110,99,108,0,0,0,1,103,100,0,13,110,111,110,111,100,101, + 64,110,111,104,111,115,116,0,0,0,22,0,0,0,0,0,106>>, + ?line 170987488 = erlang:phash(binary_to_term(ExternalFun), + 16#FFFFFFFF), + ?line 124460689 = erlang:hash(binary_to_term(ExternalFun), + 16#7FFFFFF), + case (catch erlang:phash(1,0)) of + {'EXIT',{badarg, _}} -> + {comment, Comment}; + _ -> + exit(phash_accepted_zero_as_range) + end. + + +range_test() -> + random:seed(), + F = fun(From,From,_FF) -> + ok; + (From,To,FF) -> + R = random:uniform(16#FFFFFFFFFFFFFFFF), + X = erlang:phash(R, From), + Y = erlang:phash(R, 16#100000000) - 1, + Z = (Y rem From) + 1, + case X =:= Z of + true -> + FF(From*2,To,FF); + _ -> + exit({range_test_failed, hash_on, R, range, From}) + end + end, + F(1,16#100000000,F). + + + +spread_test(N) -> + ?line test_fun(N,{erlang,phash},16#50000000000,fun(X) -> + X + end), + ?line test_fun(N,{erlang,phash},0,fun(X) -> + X + end), + ?line test_fun(N,{erlang,phash},16#123456789ABCDEF123456789ABCDEF,fun(X) -> + X + end), + ?line test_fun(N,{erlang,phash},16#50000000000,fun(X) -> + integer_to_list(X) + end), + ?line test_fun(N,{erlang,phash},16#50000000000,fun(X) -> + integer_to_bytelist(X,[]) + end), + ?line test_fun(N,{erlang,phash},16#50000000000,fun(X) -> + integer_to_binary(X) + end). + + + +cmp_test(N) -> + % No need to save seed, the error indicates what number caused it. + random:seed(), + do_cmp_hashes(N,8). +do_cmp_hashes(0,_) -> + ok; +do_cmp_hashes(N,Steps) -> + ?line R0 = random:uniform(1 bsl Steps - 1) + random:uniform(16#FFFFFFFF), + ?line R = case random:uniform(2) of + 1 -> + R0; + _ -> + -R0 + end, + ?line NSteps = case N rem 10 of + 0 -> + case (Steps + 8) rem 1024 of + 0 -> + 8; + OK -> + OK + end; + _ -> + Steps + end, + ?line X = erlang:phash(R,16#FFFFFFFF), + ?line Y = make_hash(R,16#FFFFFFFF), + ?line case X =:= Y of + true -> + do_cmp_hashes(N - 1, NSteps); + _ -> + exit({missmatch_on_input, R, phash, X, make_hash, Y}) + end. + +phash2_test() -> + Max = 1 bsl 32, + BPort = <<131,102,100,0,13,110,111,110,111,100,101,64,110,111,104, + 111,115,116,0,0,0,1,0>>, + Port = binary_to_term(BPort), + + BXPort = <<131,102,100,0,11,97,112,97,64,108,101,103,111,108,97,115, + 0,0,0,24,3>>, + XPort = binary_to_term(BXPort), + + BRef = <<131,114,0,3,100,0,13,110,111,110,111,100,101,64,110,111,104, + 111,115,116,0,0,0,1,255,0,0,0,0,0,0,0,0>>, + Ref = binary_to_term(BRef), + + BXRef = <<131,114,0,3,100,0,11,97,112,97,64,108,101,103,111,108,97,115, + 2,0,0,0,155,0,0,0,0,0,0,0,0>>, + XRef = binary_to_term(BXRef), + + BXPid = <<131,103,100,0,11,97,112,97,64,108,101,103,111,108,97,115, + 0,0,0,36,0,0,0,0,1>>, + XPid = binary_to_term(BXPid), + + + %% X = f1(), Y = f2(), Z = f3(X, Y), + + %% F1 = fun f1/0, % -> abc + B1 = <<131,112,0,0,0,66,0,215,206,77,69,249,50,170,17,129,47,21,98, + 13,196,76,242,0,0,0,1,0,0,0,0,100,0,1,116,97,1,98,2,195,126, + 58,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111, + 115,116,0,0,0,112,0,0,0,0,0>>, + F1 = binary_to_term(B1), + + %% F2 = fun f2/0, % -> abd + B2 = <<131,112,0,0,0,66,0,215,206,77,69,249,50,170,17,129,47,21,98, + 13,196,76,242,0,0,0,2,0,0,0,0,100,0,1,116,97,2,98,3,130,152, + 185,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111, + 115,116,0,0,0,112,0,0,0,0,0>>, + F2 = binary_to_term(B2), + + %% F3 = fun f3/2, % -> {abc, abd} + B3 = <<131,112,0,0,0,66,2,215,206,77,69,249,50,170,17,129,47,21,98, + 13,196,76,242,0,0,0,3,0,0,0,0,100,0,1,116,97,3,98,7,168,160, + 93,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111, + 115,116,0,0,0,112,0,0,0,0,0>>, + F3 = binary_to_term(B3), + + %% F4 = fun () -> 123456789012345678901234567 end, + B4 = <<131,112,0,0,0,66,0,215,206,77,69,249,50,170,17,129,47,21,98, + 13,196,76,242,0,0,0,4,0,0,0,0,100,0,1,116,97,4,98,2,230,21, + 171,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111, + 115,116,0,0,0,112,0,0,0,0,0>>, + F4 = binary_to_term(B4), + + %% F5 = fun() -> {X,Y,Z} end, + B5 = <<131,112,0,0,0,92,0,215,206,77,69,249,50,170,17,129,47,21,98, + 13,196,76,242,0,0,0,5,0,0,0,3,100,0,1,116,97,5,98,0,99,101, + 130,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111, + 115,116,0,0,0,112,0,0,0,0,0,100,0,3,97,98,99,100,0,3,97,98, + 100,104,2,100,0,3,97,98,99,100,0,3,97,98,100>>, + F5 = binary_to_term(B5), + + Chars = lists:seq(32,127), + NotAHeapBin = list_to_binary(lists:flatten(lists:duplicate(500,Chars))), + <<_:128,SubBin/binary>> = NotAHeapBin, + L = [%% nil + {[], 3468870702}, + + %% atom :( not very good ): + %% (cannot use block_hash due to compatibility issues...) + {abc,26499}, + {abd,26500}, + + %% small + {0,3175731469}, + {1, 539485162}, + {-1, 1117813597}, + {1 bsl 20, 1477815345}, + {-(1 bsl 20), 3076904293}, + + %% bignum + {4294967296, 2108323275}, + {-4294967296, 2586067094}, + {981494972710656, 1622082818}, + {-981494972710656, 3367191372}, + {36893488147419103232, 2545846594}, + {-36893488147419103232, 1649047068}, + {1606938044258990275541962092341162602522202993782792835301376, + 2573322433}, + {-1606938044258990275541962092341162602522202993782792835301376, + 2288753377}, + + %% binary + {<<>>, 147926629}, + {<<0:8>>, 2914887855}, + {<<0:32>>, 2014511533}, + {<<"abc">>, 1306188027}, + {<<"12345678901234567890">>, 3021061640}, + {NotAHeapBin,2644086993}, + {SubBin,3575839236}, + + %% unaligned sub binaries + {unaligned_sub_bin(<<>>), 147926629}, + {unaligned_sub_bin(<<0:8>>), 2914887855}, + {unaligned_sub_bin(<<0:32>>), 2014511533}, + {unaligned_sub_bin(<<"abc">>), 1306188027}, + {unaligned_sub_bin(<<"12345678901234567890">>), 3021061640}, + {unaligned_sub_bin(NotAHeapBin),2644086993}, + {unaligned_sub_bin(SubBin),3575839236}, + + %% bit-level binaries + {<<0:7>>, 1055790816}, + {<<"abc",13:4>>, 670412287}, + {<<5:3,"12345678901234567890">>, 289973273}, + + %% fun + {F1, 3826013332}, + {F2, 126009152}, + {F3, 3482452479}, + {F4, 633704783}, + {F5, 1241537408}, + + %% module fun + {fun lists:map/2, 840287883}, + {fun lists:map/3, 2318478565}, + {fun lists:filter/2, 635165125}, + {fun lists:filter/3, 3824649396}, + {fun xxx:map/2, 2630071865}, + {fun xxx:map/3, 4237970519}, + + %% pid + {c:pid(0,0,0), 2858162279}, + {c:pid(0,1,0), 2870503209}, + {c:pid(0,2,0), 1707788908}, + {XPid, 1290188489}, + + %% port + {Port,1954394636}, + {XPort,274735}, + + %% ref + {Ref, 1675501484}, + {XRef, 3845846926}, + + %% float + {0.0, 423528920}, + {3.14, 3731709215}, + {-3.14, 1827518724}, + + %% list + {[0.0], 167906877}, + {[{}], 4050867804}, + {[<<>>], 440873397}, + {[[]], 499070068}, + {[abc], 3112446404}, + {[a,b,c], 1505666924}, + {[a,b|c], 433753489}, + {"abc", 519996486}, + {"abc"++[1009], 290369864}, + {"abc"++[1009]++"de", 4134369195}, + {"1234567890123456", 963649519}, + + %% tuple + {{}, 221703996}, + {{{}}, 2165044361}, + {{<<>>}, 682464809}, + {{0.0}, 688441152}, + {{[]}, 1775079505}, + {{abc}, 2032039329}, + {{a,1,{},-3.14}, 1364396939}, + {{c:pid(0,2,0)}, 686997880}, + {{F4}, 2279632930}, + {{a,<<>>}, 2724468891}, + {{b,<<>>}, 2702508511} + ], + SpecFun = fun(S) -> sofs:no_elements(S) > 1 end, + F = sofs:relation_to_family(sofs:converse(sofs:relation(L))), + D = sofs:to_external(sofs:family_specification(SpecFun, F)), + ?line [] = D, + ?line [] = [{E,H,H2} || {E,H} <- L, (H2 = erlang:phash2(E, Max)) =/= H], + ok. + +-ifdef(FALSE). +f1() -> + abc. + +f2() -> + abd. + +f3(X, Y) -> + {X, Y}. +-endif. + +otp_5292_test() -> + H = fun(E) -> [erlang:hash(E, 16#7FFFFFF), + erlang:hash(-E, 16#7FFFFFF)] + end, + S1 = md5([md5(hash_int(S, E, H)) || {Start, N, Sz} <- d(), + {S, E} <- int(Start, N, Sz)]), + PH = fun(E) -> [erlang:phash(E, 1 bsl 32), + erlang:phash(-E, 1 bsl 32), + erlang:phash2(E, 1 bsl 32), + erlang:phash2(-E, 1 bsl 32)] + end, + S2 = md5([md5(hash_int(S, E, PH)) || {Start, N, Sz} <- d(), + {S, E} <- int(Start, N, Sz)]), + ?line Comment = case S1 of + <<43,186,76,102,87,4,110,245,203,177,206,6,130,69,43,99>> -> + ?line big = erlang:system_info(endian), + "Big endian machine"; + <<21,206,139,15,149,28,167,81,98,225,132,254,49,125,174,195>> -> + ?line little = erlang:system_info(endian), + "Little endian machine" + end, + ?line <<140,37,79,80,26,242,130,22,20,229,123,240,223,244,43,99>> = S2, + ?line 2 = erlang:hash(1, (1 bsl 27) -1), + ?line {'EXIT', _} = (catch erlang:hash(1, (1 bsl 27))), + {comment, Comment}. + +d() -> + [%% Start, NumOfIntervals, SizeOfInterval + {(1 bsl I)-100, 2, 100} || I <- lists:seq(1, 1000)]. + +int(Start, N, Sz) -> + {_, R} = lists:mapfoldl(fun(S, Acc) -> + {S + Sz, [{S,S+Sz-1} | Acc]} + end, [], lists:seq(Start, Start+(N-1)*Sz, Sz)), + lists:reverse(R). + +hash_int(Start, End, F) -> + HL = lists:flatmap(fun(E) -> F(E) end, lists:seq(Start, End)), + {Start, End, md5(HL)}. + +md5(T) -> + erlang:md5(term_to_binary(T)). + +bit_level_binaries() -> + ?line [3511317,7022633,14044578,28087749,56173436,112344123,90467083|_] = + bit_level_all_different(fun erlang:hash/2), + ?line [3511317,7022633,14044578,28087749,56173436,112344123,90467083|_] = + bit_level_all_different(fun erlang:phash/2), + ?line [102233154,19716,102133857,4532024,123369135,24565730,109558721|_] = + bit_level_all_different(fun erlang:phash2/2), + + ?line 13233341 = test_hash_phash(<<42:7>>, 16#7FFFFFF), + ?line 79121243 = test_hash_phash(<<99:7>>, 16#7FFFFFF), + ?line 95517726 = test_hash_phash(<<16#378ABF73:31>>, 16#7FFFFFF), + + ?line 64409098 = test_phash2(<<99:7>>, 16#7FFFFFF), + ?line 55555814 = test_phash2(<<123,19:2>>, 16#7FFFFFF), + ?line 83868582 = test_phash2(<<123,45,6:3>>, 16#7FFFFFF), + ?line 2123204 = test_phash2(<<123,45,7:3>>, 16#7FFFFFF), + + ok. + +bit_level_all_different(Hash) -> + {name,Name} = erlang:fun_info(Hash, name), + Seq = lists:seq(1, 32), + Hashes0 = [Hash(<<1:Sz>>, 16#7FFFFFF) || Sz <- Seq], + io:format("~p/2 ~p", [Name,Hashes0]), + Hashes0 = [Hash(unaligned_sub_bitstr(<<1:Sz>>), 16#7FFFFFF) || Sz <- Seq], + 32 = length(lists:usort(Hashes0)), + + Hashes1 = [Hash(<<(1 bsl (Sz-1)):Sz>>, 16#7FFFFFF) || Sz <- Seq], + io:format("~p/2 ~p", [Name,Hashes1]), + Hashes1 = [Hash(unaligned_sub_bitstr(<<(1 bsl (Sz-1)):Sz>>), 16#7FFFFFF) || + Sz <- Seq], + 32 = length(lists:usort(Hashes1)), + + Hashes2 = [Hash(<<0:Sz>>, 16#7FFFFFF) || Sz <- Seq], + io:format("~p/2 ~p", [Name,Hashes2]), + Hashes2 = [Hash(unaligned_sub_bitstr(<<0:Sz>>), 16#7FFFFFF) || Sz <- Seq], + 32 = length(lists:usort(Hashes2)), + + Hashes1. + +test_hash_phash(Bitstr, Rem) -> + Hash = erlang:hash(Bitstr, Rem), + Hash = erlang:phash(Bitstr, Rem), + Hash = erlang:hash(unaligned_sub_bitstr(Bitstr), Rem), + Hash = erlang:phash(unaligned_sub_bitstr(Bitstr), Rem). + +test_phash2(Bitstr, Rem) -> + Hash = erlang:phash2(Bitstr, Rem), + Hash = erlang:phash2(unaligned_sub_bitstr(Bitstr), Rem). + +otp_7127_test() -> + %% Used to return 2589127136. + ?line 38990304 = erlang:phash2(<<"Scott9">>), + ok. + +%% +%% Reference implementation of integer hashing +%% + +%% +%% These are primes just above 2^28 that will never be changed, they are also in +%% utils.c. +%% +-define(FN2,268439161). +-define(FN3,268435459). +-define(FN4,268436141). + +make_hash(N,M) -> + Prime1 = ?FN2, + {Prime2, BL0} = to_bytes(N), + BL = pad(BL0), + (integer_hash(BL, Prime1, Prime2) rem M) + 1. + +to_bytes(N) when N < 0 -> + {?FN4,to_bytes(-N,[])}; +to_bytes(N) -> + {?FN3,to_bytes(N,[])}. +to_bytes(0,Acc) -> + Acc; +to_bytes(N,Acc) -> + to_bytes(N bsr 8, [N band 16#FF | Acc]). + +pad([]) -> + [0,0,0,0]; +pad(L) -> + case 4 - (length(L) rem 4) of + 4 -> + L; + N -> + lists:duplicate(N,0) ++ L + end. + +integer_hash(BL,P1,P2) -> + (do_ihash(0,lists:reverse(BL),P1) * P2) band 16#FFFFFFFF. + +do_ihash(Hash,[],_) -> + Hash; +do_ihash(Hash, [H|T], P) -> + do_ihash((((Hash * P) band 16#FFFFFFFF) + H) band 16#FFFFFFFF, T, P). + + + + +%% +%% Utilities for the test of "spreading" +%% +-ifdef(debug). +hex(N) -> + hex(0,N,[]). +hex(X,0,Acc) when X >= 8 -> + [$0, $x | Acc]; +hex(X,N,Acc) -> + hex(X+1,N bsr 4, [trans(N band 16#F) | Acc]). + +trans(N) when N < 10 -> + N + $0; +trans(10) -> + $A; +trans(11) -> + $B; +trans(12) -> + $C; +trans(13) -> + $D; +trans(14) -> + $E; +trans(15) -> + $F. +-endif. + +gen_keys(N, Template, BP,Fun) -> + Ratio = (1 bsl (BP * 8)), + Low = Template + Ratio, + High = Template + (N*Ratio), + ?dbgformat("N = ~p, BP = ~p, Template = ~p, Low = ~s, High = ~s~n", + [hex(N),hex(BP),hex(Template),hex(Low),hex(High-1)]), + Fun(Template), + gen_keys2(Low, High,Ratio,Fun). + +gen_keys2(High,High2,_,_) when High >= High2 -> + []; +gen_keys2(Low,High,R,Fun) -> + Fun(Low), + gen_keys2(Low + R,High,R,Fun). + +test_fun(N,{HM,HF}, Template, Fun) -> + init_table(), + test_fun_1(0,1,N+1,{HM,HF},Template,Fun). + +test_fun_1(_,To,To,_,_,_) -> + ok; +test_fun_1(A,X,To,Y,Z,W) when A > To -> + ?dbgformat("~p:~p(~p,~p,~p,~p,~p,~p)~n",[?MODULE,test_fun_1,To,X,To,Y,Z,W]), + test_fun_1(0,X+1,To,Y,Z,W); +test_fun_1(Pos,Siz,To,{HM,HF},Template,Fun) when 1 bsl (Siz*8) =< 65536 -> + io:format("Byte: ~p, Size: ~p~n",[Pos,Siz]), + N = 1 bsl (Siz*8), + gen_keys(N,Template,Pos,fun (X) -> + P = HM:HF(Fun(X),N), + ets:insert(?MODULE,{P}) + end + ), + Hits = collect_hits(), + io:format( + "Hashing of ~p values spread over ~p buckets~n", + [N,Hits]), + case (N div Hits) > 2 of + true -> + exit({not_spread_enough, Hits, on, N}); + _ -> + test_fun_1(Pos + Siz, Siz, To,{HM,HF},Template,Fun) + end; +test_fun_1(_,_,_,_,_,_) -> + ok. + +init_table() -> + (catch ets:delete(?MODULE)), + ets:new(?MODULE,[ordered_set,named_table]). + +collect_hits() -> + N = ets:info(?MODULE,size), + init_table(), + N. + +integer_to_binary(N) -> + list_to_binary(lists:reverse(integer_to_bytelist(N,[]))). + +integer_to_bytelist(0,Acc) -> + Acc; +integer_to_bytelist(N,Acc) -> + integer_to_bytelist(N bsr 8, [N band 16#FF | Acc]). + +unaligned_sub_bin(Bin0) when is_binary(Bin0) -> + Bin1 = <<42:6,Bin0/binary,3:2>>, + Sz = size(Bin0), + <<42:6,Bin:Sz/binary,3:2>> = id(Bin1), + Bin. + +unaligned_sub_bitstr(Bin0) when is_bitstring(Bin0) -> + Bin1 = <<(-1):4,Bin0/bits,(-1):64>>, + Bits = bit_size(Bin0), + <<_:4,Bin:Bits/bits,_:64>> = id(Bin1), + Bin. + +id(I) -> I. + diff --git a/erts/emulator/test/hibernate_SUITE.erl b/erts/emulator/test/hibernate_SUITE.erl new file mode 100644 index 0000000000..4d36076d12 --- /dev/null +++ b/erts/emulator/test/hibernate_SUITE.erl @@ -0,0 +1,353 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(hibernate_SUITE). + +-include("test_server.hrl"). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + basic/1,min_heap_size/1,bad_args/1, + messages_in_queue/1,undefined_mfa/1, no_heap/1]). + +%% Used by test cases. +-export([basic_hibernator/1,messages_in_queue_restart/2, no_heap_loop/0]). + +all(suite) -> + [basic,min_heap_size,bad_args,messages_in_queue,undefined_mfa,no_heap]. + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog = ?t:timetrap(?t:minutes(3)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +%%% +%%% Testing the basic functionality of erlang:hibernate/3. +%%% + +basic(Config) when is_list(Config) -> + Ref = make_ref(), + Info = {self(),Ref}, + ExpectedHeapSz = case erlang:system_info(heap_type) of + private -> erts_debug:size([Info]); + hybrid -> erts_debug:size([a|b]) + end, + ?line Child = spawn_link(fun() -> basic_hibernator(Info) end), + ?line hibernate_wake_up(100, ExpectedHeapSz, Child), + ?line Child ! please_quit_now, + ok. + +hibernate_wake_up(0, _, _) -> ok; +hibernate_wake_up(N, ExpectedHeapSz, Child) -> + {heap_size,Before} = process_info(Child, heap_size), + case N rem 2 of + 0 -> + Child ! {acquire_old_heap,self()}, + receive + done -> ok + end; + 1 -> ok + end, + ?line Child ! {hibernate,self()}, + ?line wait_until(fun () -> + {current_function,{erlang,hibernate,3}} == + process_info(Child, current_function) + end), + ?line {message_queue_len,0} = process_info(Child, message_queue_len), + ?line {status,waiting} = process_info(Child, status), + ?line {heap_size,ExpectedHeapSz} = process_info(Child, heap_size), + io:format("Before hibernation: ~p After hibernation: ~p\n", + [Before,ExpectedHeapSz]), + ?line Child ! {whats_up,self()}, + ?line receive + {all_fine,X,Child,_Ref} -> + if + N =:= 1 -> io:format("~p\n", [X]); + true -> ok + end, + {backtrace,Bin} = process_info(Child, backtrace), + if + size(Bin) > 1000 -> + io:format("~s\n", [binary_to_list(Bin)]), + ?line ?t:fail(stack_is_growing); + true -> + hibernate_wake_up(N-1, ExpectedHeapSz, Child) + end; + Other -> + ?line io:format("~p\n", [Other]), + ?line ?t:fail(unexpected_message) + end. + +basic_hibernator(Info) -> + {catchlevel,0} = process_info(self(), catchlevel), + receive + Any -> + basic_hibernator_msg(Any, Info), + basic_hibernator(Info) + end. + +basic_hibernator_msg({hibernate,_}, Info) -> + catch erlang:hibernate(?MODULE, basic_hibernator, [Info]), + exit(hibernate_returned); +basic_hibernator_msg({acquire_old_heap,Parent}, _) -> + acquire_old_heap(), + Parent ! done; +basic_hibernator_msg({whats_up,Parent}, {Parent,Ref}) -> + {heap_size,HeapSize} = process_info(self(), heap_size), + io:format("Heap size after waking up: ~p\n", [HeapSize]), + X = whats_up_calc(5000, 2, math:pi(), 4, 5, 6, 7, 8.5, 9, []), + Parent ! {all_fine,X,self(),Ref}; +basic_hibernator_msg(please_quit_now, _) -> + exit(normal); +basic_hibernator_msg(Other, _) -> + exit({unexpected,Other}). + +acquire_old_heap() -> + case process_info(self(), [heap_size,total_heap_size]) of + [{heap_size,Sz},{total_heap_size,Total}] when Sz < Total -> + ok; + _ -> + acquire_old_heap() + end. + +%% The point with this calculation is to force memory to be +%% allocated for the argument registers in the process structure. +%% The allocation will be forced if the process is scheduled out +%% while calling a function with more than 6 arguments. +whats_up_calc(0, A2, A3, A4, A5, A6, A7, A8, A9, Acc) -> + {Acc,A2+A3+A4+A5+A6+A7+A8+A9}; +whats_up_calc(A1, A2, A3, A4, A5, A6, A7, A8, A9, Acc) -> + whats_up_calc(A1-1, A2+1, A3+2, A4+3, A5+4, A6+5, A7+6, A8+7, A9+8, [A1,A2|Acc]). + +%%% +%%% Testing setting the minimum heap size. +%%% + +min_heap_size(Config) when is_list(Config) -> + ?line erlang:trace(new, true, [call]), + MFA = {?MODULE,min_hibernator,1}, + ?line 1 = erlang:trace_pattern(MFA, true, [local]), + Ref = make_ref(), + Info = {self(),Ref}, + ?line Child = spawn_opt(fun() -> min_hibernator(Info) end, + [{min_heap_size,15000},link]), + receive + {trace,Child,call,{?MODULE,min_hibernator,_}} -> + ?line 1 = erlang:trace_pattern(MFA, false, [local]), + ?line erlang:trace(new, false, [call]) + end, + {heap_size,HeapSz} = process_info(Child, heap_size), + io:format("Heap size: ~p\n", [HeapSz]), + ?line if + HeapSz < 20 -> ok + end, + ?line Child ! wake_up, + receive + {heap_size,AfterSize} -> + io:format("Heap size after wakeup: ~p\n", [AfterSize]), + ?line + if + AfterSize >= 15000 -> ok + end; + Other -> + io:format("Unexpected: ~p\n", [Other]), + ?line ?t:fail() + end. + +min_hibernator({Parent,_Ref}) -> + erlang:hibernate(erlang, apply, [fun min_hibernator_recv/1, [Parent]]). + +min_hibernator_recv(Parent) -> + receive + wake_up -> + Parent ! process_info(self(), heap_size) + end. + +%%% +%%% Testing feeding erlang:hibernate/3 with bad arguments. +%%% + +bad_args(Config) when is_list(Config) -> + ?line bad_args(?MODULE, {name,glurf}, [0]), + ?line {'EXIT',{system_limit,_}} = + (catch erlang:hibernate(x, y, lists:duplicate(5122, xxx))), + ?line bad_args(42, name, [0]), + ?line bad_args(xx, 42, [1]), + ?line bad_args(xx, 42, glurf), + ?line bad_args(xx, 42, {}), + ?line bad_args({}, name, [2]), + ?line bad_args({1}, name, [3]), + ?line bad_args({1,2,3}, name, [4]), + ?line bad_args({1,2,3}, name, [5]), + ?line bad_args({1,2,3,4}, name, [6]), + ?line bad_args({1,2,3,4,5,6}, name,[7]), + ?line bad_args({1,2,3,4,5}, name, [8]), + ?line bad_args({1,2}, name, [9]), + ?line bad_args([1,2], name, [9]), + ?line bad_args(55.0, name, [9]), + ok. + +bad_args(Mod, Name, Args) -> + Res = (catch erlang:hibernate(Mod, Name, Args)), + erlang:garbage_collect(), + case Res of + {'EXIT',{badarg,_Where}} -> + io:format("erlang:hibernate(~p, ~p, ~p) -> ~p\n", [Mod,Name,Args,Res]); + Other -> + io:format("erlang:hibernate(~p, ~p, ~p) -> ~p\n", [Mod,Name,Args,Res]), + ?t:fail({bad_result,Other}) + end. + + +%%% +%%% Testing calling erlang:hibernate/3 with messages already in the message queue. +%%% + +messages_in_queue(Config) when is_list(Config) -> + Self = self(), + Msg = {Self,make_ref(),a,message}, + Pid = spawn_link(fun() -> messages_in_queue_1(Self, Msg) end), + Pid ! Msg, + Pid ! go_ahead, + receive + done -> ok; + Other -> + ?line io:format("~p\n", [Other]), + ?line ?t:fail(unexpected_message) + end. + +messages_in_queue_1(Parent, ExpectedMsg) -> + receive + go_ahead -> ok + end, + {message_queue_len,1} = process_info(self(), message_queue_len), + erlang:hibernate(?MODULE, messages_in_queue_restart, + [Parent,ExpectedMsg]). + +messages_in_queue_restart(Parent, ExpectedMessage) -> + ?line receive + ExpectedMessage -> + Parent ! done; + Other -> + io:format("~p\n", [Other]), + ?t:fail(unexpected_message) + end, + ok. + + +%%% +%%% Test that trying to hibernate to an undefined MFA gives the correct +%%% exit behavior. +%%% + +undefined_mfa(Config) when is_list(Config) -> + ?line process_flag(trap_exit, true), + ?line Pid = spawn_link(fun() -> + %% Will be a call_only instruction. + erlang:hibernate(?MODULE, blarf, []) end), + ?line Pid ! {a,message}, + ?line receive + {'EXIT',Pid,{undef,Undef}} -> + io:format("~p\n", [Undef]), + ok; + Other -> + ?line io:format("~p\n", [Other]), + ?line ?t:fail(unexpected_message) + end, + undefined_mfa_1(). + +undefined_mfa_1() -> + ?line Pid = spawn_link(fun() -> + %% Force a call_last instruction by calling bar() + %% (if that is not obvious). + bar(), + erlang:hibernate(?MODULE, blarf, []) + end), + ?line Pid ! {another,message}, + ?line receive + {'EXIT',Pid,{undef,Undef}} -> + io:format("~p\n", [Undef]), + ok; + Other -> + ?line io:format("~p\n", [Other]), + ?line ?t:fail(unexpected_message) + end, + ok. + +bar() -> + ok. + +%% +%% No heap +%% + +no_heap(doc) -> []; +no_heap(suite) -> []; +no_heap(Config) when is_list(Config) -> + ?line H = spawn_link(fun () -> clean_dict(), no_heap_loop() end), + ?line lists:foreach(fun (_) -> + wait_until(fun () -> is_hibernated(H) end), + ?line [{heap_size,1}, + {total_heap_size,1}] + = process_info(H, + [heap_size, + total_heap_size]), + receive after 10 -> ok end, + H ! again + end, + lists:seq(1, 100)), + ?line unlink(H), + ?line exit(H, bye). + +no_heap_loop() -> + flush(), + erlang:hibernate(?MODULE, no_heap_loop, []). + +clean_dict() -> + {dictionary, Dict} = process_info(self(), dictionary), + lists:foreach(fun ({Key, _}) -> erase(Key) end, Dict). + +%% +%% Misc +%% + +is_hibernated(P) -> + case process_info(P, [current_function, status]) of + [{current_function, {erlang, hibernate, _}}, + {status, waiting}] -> + true; + _ -> + false + end. + +flush() -> + receive + _Msg -> flush() + after 0 -> + ok + end. + + +wait_until(Fun) -> + case catch Fun() of + true -> ok; + _ -> receive after 10 -> wait_until(Fun) end + end. diff --git a/erts/emulator/test/ignore_cores.erl b/erts/emulator/test/ignore_cores.erl new file mode 120000 index 0000000000..1d738cbafd --- /dev/null +++ b/erts/emulator/test/ignore_cores.erl @@ -0,0 +1 @@ +../../test/ignore_cores.erl
\ No newline at end of file diff --git a/erts/emulator/test/list_bif_SUITE.erl b/erts/emulator/test/list_bif_SUITE.erl new file mode 100644 index 0000000000..65ea88eb2f --- /dev/null +++ b/erts/emulator/test/list_bif_SUITE.erl @@ -0,0 +1,145 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(list_bif_SUITE). +-include("test_server.hrl"). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2]). +-export([hd_test/1,tl_test/1,t_length/1,t_list_to_pid/1, + t_list_to_float/1,t_list_to_integer/1]). + + +all(suite) -> + [hd_test,tl_test,t_length,t_list_to_pid,t_list_to_float,t_list_to_integer]. + +init_per_testcase(_Case, Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(60)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +t_list_to_integer(suite) -> + []; +t_list_to_integer(doc) -> + ["tests list_to_integer and string:to_integer"]; +t_list_to_integer(Config) when is_list(Config) -> + ?line {'EXIT',{badarg,_}} = (catch list_to_integer("12373281903728109372810937209817320981321ABC")), + ?line 12373281903728109372810937209817320981321 = (catch list_to_integer("12373281903728109372810937209817320981321")), + ?line 12373 = (catch list_to_integer("12373")), + ?line -12373 = (catch list_to_integer("-12373")), + ?line 12373 = (catch list_to_integer("+12373")), + ?line {'EXIT',{badarg,_}} = ( catch list_to_integer(abc)), + ?line {'EXIT',{badarg,_}} = (catch list_to_integer("")), + ?line {12373281903728109372810937209817320981321,"ABC"} = string:to_integer("12373281903728109372810937209817320981321ABC"), + ?line {-12373281903728109372810937209817320981321,"ABC"} = string:to_integer("-12373281903728109372810937209817320981321ABC"), + ?line {12,[345]} = string:to_integer([$1,$2,345]), + ?line {12,[a]} = string:to_integer([$1,$2,a]), + ?line {error,no_integer} = string:to_integer([$A]), + ?line {error,not_a_list} = string:to_integer($A), + ok. + +%% Test hd/1 with correct and incorrect arguments. +hd_test(Config) when is_list(Config) -> + ?line $h = hd(id("hejsan")), + ?line case catch hd(id($h)) of + {'EXIT', {badarg, _}} -> ok; + Res -> + Str=io_lib:format("hd/1 with incorrect args "++ + "succeeded.~nResult: ~p", [Res]), + test_server:fail(Str) + end, + ok. + + +%% Test tl/1 with correct and incorrect arguments. +tl_test(Config) when is_list(Config) -> + ?line "ejsan" = tl(id("hejsan")), + ?line case catch tl(id(104)) of + {'EXIT', {badarg, _}} -> + ok; + Res -> + Str=io_lib:format("tl/1 with incorrect args "++ + "succeeded.~nResult: ~p", [Res]), + test_server:fail(Str) + end, + ok. + + +%% Test length/1 with correct and incorrect arguments. + +t_length(Config) when is_list(Config) -> + ?line 0 = length(""), + ?line 0 = length([]), + ?line 1 = length([1]), + ?line 2 = length([1,a]), + ?line 2 = length("ab"), + ?line 3 = length("abc"), + ?line 4 = length(id([x|"abc"])), + ?line 6 = length("hejsan"), + ?line {'EXIT',{badarg,_}} = (catch length(id([a,b|c]))), + ?line case catch length({tuple}) of + {'EXIT', {badarg, _}} -> + ok; + Res -> + Str = io_lib:format("length/1 with incorrect args "++ + "succeeded.~nResult: ~p", [Res]), + ?line test_server:fail(Str) + end, + ok. + + +%% Test list_to_pid/1 with correct and incorrect arguments. + +t_list_to_pid(Config) when is_list(Config) -> + ?line Me = self(), + ?line MyListedPid = pid_to_list(Me), + ?line Me = list_to_pid(MyListedPid), + ?line case catch list_to_pid(id("Incorrect list")) of + {'EXIT', {badarg, _}} -> + ok; + Res -> + Str=io_lib:format("list_to_pid/1 with incorrect "++ + "arg succeeded.~nResult: ~p", + [Res]), + test_server:fail(Str) + end, + ok. + + +%% Test list_to_float/1 with correct and incorrect arguments. + +t_list_to_float(Config) when is_list(Config) -> + ?line 5.89000 = list_to_float(id("5.89")), + ?line 5.89898 = list_to_float(id("5.89898")), + ?line case catch list_to_float(id("58")) of + {'EXIT', {badarg, _}} -> ok; + Res -> + Str=io_lib:format("list_to_float with incorrect "++ + "arg succeeded.~nResult: ~p", + [Res]), + test_server:fail(Str) + end, + ok. + +id(I) -> I. + + diff --git a/erts/emulator/test/long_timers_test.erl b/erts/emulator/test/long_timers_test.erl new file mode 100644 index 0000000000..28626d26fb --- /dev/null +++ b/erts/emulator/test/long_timers_test.erl @@ -0,0 +1,317 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + + +%%%------------------------------------------------------------------- +%%% File : long_timer_test.erl +%%% Author : Rickard Green <[email protected]> +%%% Description : +%%% +%%% Created : 21 Aug 2006 by Rickard Green <[email protected]> +%%%------------------------------------------------------------------- + + +-define(MAX_TIMEOUT, 60). % Minutes +-define(MAX_LATE, 10*1000). % Milliseconds +-define(REG_NAME, '___LONG___TIMERS___TEST___SERVER___'). + +-define(DRV_NAME, timer_driver). + +% First byte in communication with the timer driver +-define(START_TIMER, 0). +-define(CANCEL_TIMER, 1). +-define(DELAY_START_TIMER, 2). +-define(TIMER, 3). +-define(CANCELLED, 4). + +-module(long_timers_test). + +-export([start/1, check_result/0]). + +-record(timeout_rec,{pid, type, timeout, timeout_diff}). + +start(DrvDir) when is_list(DrvDir) -> + Starter = self(), + StartDone = make_ref(), + stop_node(full_node_name(?REG_NAME)), + Node = start_node(?REG_NAME), + Test = spawn(Node, fun () -> test(Starter, DrvDir, StartDone) end), + Mon = erlang:monitor(process, Test), + receive + StartDone -> + erlang:demonitor(Mon), + net_kernel:disconnect(Node), + receive {'DOWN',Mon,_,_,_} -> ok after 0 -> ok end; + {'DOWN',Mon,_,_,Reason} -> + stop_node(full_node_name(?REG_NAME)), + {error, Reason} + end. + +check_result() -> + Node = full_node_name(?REG_NAME), + LTTS = {?REG_NAME, Node}, + Mon = erlang:monitor(process, LTTS), + (catch LTTS ! {get_result, ?REG_NAME, self()}), + receive + {'DOWN', Mon, process, _, Reason} -> + {?REG_NAME, 'DOWN', Reason}; + {result, ?REG_NAME, TORs, Start, End} -> + erlang:demonitor(Mon), + receive {'DOWN', Mon, _, _, _} -> ok after 0 -> ok end, + stop_node(Node), + check(TORs, (timer:now_diff(End, Start) div 1000) - ?MAX_LATE, ok) + end. + +check([#timeout_rec{timeout = Timeout, + type = Type, + timeout_diff = undefined} | TORs], + NeedRes, + _Ok) when Timeout < NeedRes -> + io:format("~p timeout = ~p failed! No timeout.~n", + [Type, Timeout]), + check(TORs, NeedRes, failed); +check([#timeout_rec{timeout_diff = undefined} | TORs], + NeedRes, + Ok) -> + check(TORs, NeedRes, Ok); +check([#timeout_rec{timeout = Timeout, + type = Type, + timeout_diff = {error, Reason}} | TORs], + NeedRes, + _Ok) -> + io:format("~p timeout = ~p failed! exit reason ~p~n", + [Type, Timeout, Reason]), + check(TORs, NeedRes, failed); +check([#timeout_rec{timeout = Timeout, + type = Type, + timeout_diff = TimeoutDiff} | TORs], + NeedRes, + Ok) -> + case (0 =< TimeoutDiff) and (TimeoutDiff =< ?MAX_LATE) of + true -> + io:format("~p timeout = ~p succeded! timeout diff = ~p.~n", + [Type, Timeout, TimeoutDiff]), + check(TORs, NeedRes, Ok); + false -> + io:format("~p timeout = ~p failed! timeout diff = ~p.~n", + [Type, Timeout, TimeoutDiff]), + check(TORs, NeedRes, failed) + end; +check([], _NeedRes, Ok) -> + Ok. + +receive_after(Timeout) -> + Start = now(), + receive + {get_result, ?REG_NAME} -> + ?REG_NAME ! #timeout_rec{pid = self(), + type = receive_after, + timeout = Timeout} + after Timeout -> + Stop = now(), + receive + {get_result, ?REG_NAME} -> + TimeoutDiff = ((timer:now_diff(Stop, Start) div 1000) + - Timeout), + ?REG_NAME ! #timeout_rec{pid = self(), + type = receive_after, + timeout = Timeout, + timeout_diff = TimeoutDiff} + end + end. + +driver(Timeout) -> + Port = open_port({spawn, ?DRV_NAME},[]), + link(Port), + Start = now(), + erlang:port_command(Port, <<?START_TIMER, Timeout:32>>), + receive + {get_result, ?REG_NAME} -> + ?REG_NAME ! #timeout_rec{pid = self(), + type = driver, + timeout = Timeout}; + {Port,{data,[?TIMER]}} -> + Stop = now(), + unlink(Port), + true = erlang:port_close(Port), + receive + {get_result, ?REG_NAME} -> + TimeoutDiff = ((timer:now_diff(Stop, Start) div 1000) + - Timeout), + ?REG_NAME ! #timeout_rec{pid = self(), + type = driver, + timeout = Timeout, + timeout_diff = TimeoutDiff} + end + end. + +bif_timer(Timeout) -> + Tmr = erlang:start_timer(Timeout, self(), ok), + Start = now(), + receive + {get_result, ?REG_NAME} -> + ?REG_NAME ! #timeout_rec{pid = self(), + type = bif_timer, + timeout = Timeout}; + {timeout, Tmr, ok} -> + Stop = now(), + receive + {get_result, ?REG_NAME} -> + TimeoutDiff = ((timer:now_diff(Stop, Start) div 1000) + - Timeout), + ?REG_NAME ! #timeout_rec{pid = self(), + type = bif_timer, + timeout = Timeout, + timeout_diff = TimeoutDiff} + end + end. + +test(Starter, DrvDir, StartDone) -> + erl_ddll:start(), + ok = load_driver(DrvDir, ?DRV_NAME), + process_flag(trap_exit, true), + register(?REG_NAME, self()), + {group_leader, GL} = process_info(whereis(net_kernel),group_leader), + group_leader(GL, self()), + Start = now(), + TORs = lists:map(fun (Min) -> + TO = Min*60*1000, + [#timeout_rec{pid = spawn_opt( + fun () -> + receive_after(TO) + end, + [link, {priority, high}]), + type = receive_after, + timeout = TO}, + #timeout_rec{pid = spawn_opt( + fun () -> + driver(TO) + end, + [link, {priority, high}]), + type = driver, + timeout = TO}, + #timeout_rec{pid = spawn_opt( + fun () -> + bif_timer(TO) + end, + [link, {priority, high}]), + type = bif_timer, + timeout = TO}] + end, + lists:seq(1, ?MAX_TIMEOUT)), + FlatTORs = lists:flatten(TORs), + Starter ! StartDone, + test_loop(FlatTORs, Start). + +test_loop(TORs, Start) -> + receive + {get_result, ?REG_NAME, Pid} -> + End = now(), + Pid ! {result, ?REG_NAME, get_test_results(TORs), Start, End}, + erl_ddll:unload_driver(?DRV_NAME), + erl_ddll:stop(), + exit(bye) + end. + +get_test_results(TORs) -> + lists:foreach(fun (#timeout_rec{pid = Pid}) -> + Pid ! {get_result, ?REG_NAME} + end, + TORs), + get_test_results(TORs, []). + +get_test_results([#timeout_rec{pid = Pid, + timeout = Timeout} = TOR | TORs], NewTORs) -> + receive + #timeout_rec{pid = Pid, timeout = Timeout} = NewTOR -> + get_test_results(TORs, [NewTOR | NewTORs]); + #timeout_rec{pid = Pid} = NewTOR -> + exit({timeout_mismatch, TOR, NewTOR}); + {'EXIT', Pid, Reason} -> + get_test_results(TORs, + [TOR#timeout_rec{timeout_diff = {error, Reason}} + | NewTORs]) + end; +get_test_results([], NewTORs) -> + lists:reverse(NewTORs). + +mk_node_cmdline(Name) -> + Static = "-detached -noinput", + Pa = filename:dirname(code:which(?MODULE)), + Prog = case catch init:get_argument(progname) of + {ok,[[P]]} -> P; + _ -> exit(no_progname_argument_found) + end, + NameSw = case net_kernel:longnames() of + false -> "-sname "; + true -> "-name "; + _ -> exit(not_distributed_node) + end, + {ok, Pwd} = file:get_cwd(), + NameStr = atom_to_list(Name), + Prog ++ " " + ++ Static ++ " " + ++ NameSw ++ " " ++ NameStr ++ " " + ++ "-pa " ++ Pa ++ " " + ++ "-env ERL_CRASH_DUMP " ++ Pwd ++ "/erl_crash_dump." ++ NameStr ++ " " + ++ "-setcookie " ++ atom_to_list(erlang:get_cookie()). + +full_node_name(PreName) -> + HostSuffix = lists:dropwhile(fun ($@) -> false; (_) -> true end, + atom_to_list(node())), + list_to_atom(atom_to_list(PreName) ++ HostSuffix). + +ping_node(_Node, 0) -> + pang; +ping_node(Node, N) when is_integer(N), N > 0 -> + case catch net_adm:ping(Node) of + pong -> pong; + _ -> + receive after 100 -> ok end, + ping_node(Node, N-1) + end. + +start_node(Name) -> + FullName = full_node_name(Name), + CmdLine = mk_node_cmdline(Name), + io:format("Starting node ~p: ~s~n", [FullName, CmdLine]), + case open_port({spawn, CmdLine}, []) of + Port when is_port(Port) -> + unlink(Port), + erlang:port_close(Port), + case ping_node(FullName, 50) of + pong -> FullName; + Other -> exit({failed_to_start_node, FullName, Other}) + end; + Error -> + exit({failed_to_start_node, FullName, Error}) + end. + +stop_node(Node) -> + monitor_node(Node, true), + spawn(Node, fun () -> halt() end), + receive {nodedown, Node} -> ok end. + +load_driver(Dir, Driver) -> + case erl_ddll:load_driver(Dir, Driver) of + ok -> ok; + {error, Error} = Res -> + io:format("~s\n", [erl_ddll:format_error(Error)]), + Res + end. diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl new file mode 100644 index 0000000000..69c89f5d2d --- /dev/null +++ b/erts/emulator/test/match_spec_SUITE.erl @@ -0,0 +1,942 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(match_spec_SUITE). + +-export([all/1, not_run/1]). +-export([test_1/1, test_2/1, test_3/1, bad_match_spec_bin/1, + trace_control_word/1, silent/1, silent_no_ms/1, + ms_trace2/1, ms_trace3/1, boxed_and_small/1, + destructive_in_test_bif/1, guard_exceptions/1, + unary_plus/1, unary_minus/1, moving_labels/1]). +-export([fpe/1]). + +-export([runner/2]). +-export([f1/1, f2/2, f3/2, fn/1, fn/2, fn/3]). +-export([do_boxed_and_small/0]). + +% This test suite assumes that tracing in general works. What we test is +% the match spec functionality. + +-include("test_server.hrl"). + +-export([init_per_testcase/2, fin_per_testcase/2]). + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog=?t:timetrap(?t:seconds(10)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + + +all(suite) -> + case test_server:is_native(?MODULE) of + false -> [test_1, test_2, test_3, bad_match_spec_bin, + trace_control_word, silent, silent_no_ms, + ms_trace2, ms_trace3, boxed_and_small, + destructive_in_test_bif, guard_exceptions, + unary_plus, unary_minus, fpe, moving_labels]; + true -> [not_run] + end. + +not_run(Config) when is_list(Config) -> + {skipped, "Native Code"}. + +test_1(doc) -> + [""]; +test_1(suite) -> []; +test_1(Config) when is_list(Config) -> + ?line tr(fun() -> ?MODULE:f1(a) end, + {?MODULE, f1, 1}, + [], + [{call, {?MODULE, f1, [a]}}]), + + ?line tr(fun() -> ?MODULE:f2(a, a) end, + {?MODULE, f2, 2}, + [{['$1','$1'],[{is_atom, '$1'}],[]}], + [{call, {?MODULE, f2, [a, a]}}]), + + ?line tr(fun() -> ?MODULE:f2(a, a) end, + {?MODULE, f2, 2}, + [{['$1','$1'],[{is_atom, '$1'}],[{message, false}]}], + []), + + ?line tr(fun() -> ?MODULE:f2(a, a) end, + {?MODULE, f2, 2}, + [{['$1','$1'],[{is_atom, '$1'}],[{message, 4711}]}], + [{call, {?MODULE, f2, [a, a]}, 4711}]), + + Ref = make_ref(), + ?line tr(fun() -> ?MODULE:f2(Ref, Ref) end, + {?MODULE, f2, 2}, + [{[Ref,'$1'],[{is_reference, '$1'}],[{message, 4711}]}], + [{call, {?MODULE, f2, [Ref, Ref]}, 4711}]), + ?line tr(fun() -> ?MODULE:f2(Ref, Ref) end, + {?MODULE, f2, 2}, + [{['$1',Ref],[{is_reference, '$1'}],[{message, 4711}]}], + [{call, {?MODULE, f2, [Ref, Ref]}, 4711}]), + + ?line tr(fun() -> ?MODULE:f2(a, a) end, + {?MODULE, f2, 2}, + [{['$0','$0'],[{is_atom, '$0'}],[{message, 4711}]}], + [{call, {?MODULE, f2, [a, a]}, 4711}]), + + ?line tr(fun() -> ?MODULE:f2(a, b) end, + {?MODULE, f2, 2}, + [{['_','_'],[],[]}], + [{call, {?MODULE, f2, [a, b]}}]), + + ?line tr(fun() -> ?MODULE:f2(a, b) end, + {?MODULE, f2, 2}, + [{['_','_'],[],[{message, '$_'}]}], + [{call, {?MODULE, f2, [a, b]}, [a, b]}]), + + ?line tr(fun() -> ?MODULE:f2(a, '$_') end, + {?MODULE, f2, 2}, + [{['$1','$_'],[{is_atom, '$1'}],[]}], + [{call, {?MODULE, f2, [a, '$_']}}]), + + ?line tr(fun() -> ?MODULE:f1({a}) end, + {?MODULE, f1, 1}, + [{['$1'],[{'==', '$1', {const, {a}}}],[]}], + [{call, {?MODULE, f1, [{a}]}}]), + + ?line tr(fun() -> ?MODULE:f1({a}) end, + {?MODULE, f1, 1}, + [{['$1'],[{'==', '$1', {{a}}}],[]}], + [{call, {?MODULE, f1, [{a}]}}]), + +%% Undocumented, currently. + ?line tr(fun() -> ?MODULE:f2(a, a) end, + {?MODULE, f2, 2}, + [{['$1','$1'],[{is_atom, '$1'}],[{message, 4711}, + {message, true}]}], + [{call, {?MODULE, f2, [a, a]}}]), + + ?line tr(fun() -> ?MODULE:f2(a, a) end, + {?MODULE, f2, 2}, + [{['$1','$1'],[{is_atom, '$1'}],[{message, 4711}, + {message, false}]}], + []), + + ?line tr(fun() -> ?MODULE:f2(a, a) end, + {?MODULE, f2, 2}, + [{['$1','$1'],[{is_atom, '$1'}],[kakalorum]}], + [{call, {?MODULE, f2, [a, a]}}]), + +% case tr0(fun() -> ?MODULE:f2(a, a) end, +% {?MODULE, f2, 2}, +% [{['$1','$1'],[{is_atom, '$1'}],[{message, {process_dump}}]}]) of +% [{trace, _, call, {?MODULE, f2, [a, a]}, Bin}] -> +% erlang:display(binary_to_list(Bin)) +% end, + +% Error cases + ?line errchk([{['$1','$1'],[{is_atom, '$1'}],[{banka, kanin}]}]), + + ok. + +test_2(doc) -> + [""]; +test_2(suite) -> []; +test_2(Config) when is_list(Config) -> + ?line tr(fun() -> ?MODULE:f2(a, a) end, + {?MODULE, f2, 2}, + [{['$1','$1'],[{is_atom, '$1'}],[{return_trace}]}], + [{call, {?MODULE, f2, [a, a]}}, + {return_from, {?MODULE, f2, 2}, {a, a}}]), + ok. + +test_3(doc) -> + ["Test the enable_trace/2 and caller/0 PAM instructions"]; +test_3(suite) -> []; +test_3(Config) when is_list(Config) -> + ?line Fun1 = fun() -> + register(fnoppelklopfer,self()), + ?MODULE:f2(a, b), + ?MODULE:f2(a, b) + end, + ?line P1 = spawn(?MODULE, runner, [self(), Fun1]), + ?line Pat = [{['$1','$1'],[],[{message, + [{enable_trace, P1, call},{caller}]}]}, + {['_','_'],[],[{message, + [{disable_trace, fnoppelklopfer, call}]}]}], + ?line Fun2 = fun() -> ?MODULE:f3(a, a) end, + ?line P2 = spawn(?MODULE, runner, [self(), Fun2]), + ?line erlang:trace(P2, true, [call]), + ?line erlang:trace_pattern({?MODULE, f2, 2}, Pat), + ?line collect(P2, [{trace, P2, call, {?MODULE, f2, [a, a]}, [true, + {?MODULE,f3,2}]}]), + ?line collect(P1, [{trace, P1, call, {?MODULE, f2, [a, b]}, [true]}]), + ?line ok. + +bad_match_spec_bin(Config) when is_list(Config) -> + {'EXIT',{badarg,_}} = (catch ets:match_spec_run([1], <<>>)), + B0 = <<1,2>>, + {B,_} = split_binary(B0, 0), + {'EXIT',{badarg,_}} = (catch ets:match_spec_run([1], B)), + ok. + + + +trace_control_word(doc) -> + ["Test the erlang:system_info(trace_control_word) and ", + "erlang:system_flag(trace_control_word, Value) BIFs, ", + "as well as the get_tcw/0 and set_tcw/1 PAM instructions"]; +trace_control_word(suite) -> []; +trace_control_word(Config) when is_list(Config) -> + ?line 32 = Bits = tcw_bits(), + ?line High = 1 bsl (Bits - 1), + ?line erlang:system_flag(trace_control_word, 17), + ?line tr(fun() -> ?MODULE:f1(a) end, + {?MODULE, f1, 1}, + [{'_',[{'=:=', {get_tcw}, 17}],[]}], + [{call, {?MODULE, f1, [a]}}]), + ?line tr(fun() -> ?MODULE:f1(a) end, + {?MODULE, f1, 1}, + [{'_',[{'=:=', {get_tcw}, 18}],[]}], + []), + ?line erlang:system_flag(trace_control_word, High), + ?line tr(fun() -> ?MODULE:f1(a) end, + {?MODULE, f1, 1}, + [{'_',[{'=:=', {get_tcw}, High}],[]}], + [{call, {?MODULE, f1, [a]}}]), + ?line erlang:system_flag(trace_control_word, 0), + ?line tr(fun() -> + ?MODULE:f1(a), + ?MODULE:f1(start), + ?MODULE:f1(b), + ?MODULE:f1(c), + ?MODULE:f1(high), + ?MODULE:f1(d), + ?MODULE:f1(stop), + ?MODULE:f1(e) + end, + {?MODULE, f1, 1}, + [{[start], + [], + [{message, {set_tcw, 17}}]}, + {[stop], + [], + [{message, {set_tcw, 0}}]}, + {[high], + [], + [{message, {set_tcw, High}}]}, + {['_'], + [{'>', {get_tcw}, 0}], + [{set_tcw, {'+', 1, {get_tcw}}}, {message, {get_tcw}}] }], + [{call, {?MODULE, f1, [start]}, 0}, + {call, {?MODULE, f1, [b]}, 18}, + {call, {?MODULE, f1, [c]}, 19}, + {call, {?MODULE, f1, [high]}, 19}, + {call, {?MODULE, f1, [d]}, High + 1}, + {call, {?MODULE, f1, [stop]}, High + 1}]), + ?line 0 = erlang:system_info(trace_control_word), + ok. + +tcw_bits() -> + ?line tcw_bits(erlang:system_flag(trace_control_word, 0), 0, 0). + +tcw_bits(Save, Prev, Bits) -> + ?line Curr = 1 bsl Bits, + ?line case catch erlang:system_flag(trace_control_word, Curr) of + {'EXIT' , {badarg, _}} -> + ?line Prev = erlang:system_flag(trace_control_word, Save), + Bits; + Prev -> + ?line Curr = erlang:system_info(trace_control_word), + tcw_bits(Save, Curr, Bits+1) + end. + + + +silent(doc) -> + ["Test the erlang:trace(_, _, [silent]) flag ", + "as well as the silent/0 PAM instruction"]; +silent(suite) -> []; +silent(Config) when is_list(Config) -> + %% Global call trace + ?line tr(fun() -> + ?MODULE:f1(a), % No trace - not active + ?MODULE:f1(miss), % No trace - no activation + ?MODULE:f1(b), % No trace - still not active + ?MODULE:f1(start), % Trace - activation + ?MODULE:f1(c), % Trace - active + f1(d), % No trace - local call + ?MODULE:f1(miss), % Trace - no inactivation + ?MODULE:f1(e), % Trace - still active + ?MODULE:f1(stop), % No trace - inactivation + ?MODULE:f1(f) % No trace - not active + end, + {?MODULE, f1, 1}, + [call, silent], + [{[start], + [], + [{silent, false}, {message, start}]}, + {[stop], + [], + [{silent, true}, {message, stop}]}, + {[miss], + [], + [{silent, neither_true_nor_false}, {message, miss}]}, + {['$1'], + [], + [{message, '$1'}] }], + [global], + [{call, {?MODULE, f1, [start]}, start}, + {call, {?MODULE, f1, [c]}, c}, + {call, {?MODULE, f1, [miss]}, miss}, + {call, {?MODULE, f1, [e]}, e} ]), + %% Local call trace + ?line tr(fun() -> + ?MODULE:f1(a), % No trace - not active + f1(b), % No trace - not active + ?MODULE:f1(start), % Trace - activation + ?MODULE:f1(c), % Trace - active + f1(d), % Trace - active + f1(stop), % No trace - inactivation + ?MODULE:f1(e), % No trace - not active + f1(f) % No trace - not active + end, + {?MODULE, f1, 1}, + [call, silent], + [{[start], + [], + [{silent, false}, {message, start}]}, + {[stop], + [], + [{silent, true}, {message, stop}]}, + {['$1'], + [], + [{message, '$1'}] }], + [local], + [{call, {?MODULE, f1, [start]}, start}, + {call, {?MODULE, f1, [c]}, c}, + {call, {?MODULE, f1, [d]}, d} ]), + ok. + +silent_no_ms(doc) -> + ["Test the erlang:trace(_, _, [silent]) flag without match specs"]; +silent_no_ms(suite) -> []; +silent_no_ms(Config) when is_list(Config) -> + %% Global call trace + %% + %% Trace f2/2 and erlang:integer_to_list/1 without match spec + %% and use match spec on f1/1 to control silent flag. + ?line tr( + fun () -> + ?MODULE:f1(a), + ?MODULE:f2(b, c), + erlang:integer_to_list(id(1)), + ?MODULE:f3(d, e), + ?MODULE:f1(start), + ?MODULE:f2(f, g), + erlang:integer_to_list(id(2)), + ?MODULE:f3(h, i), + ?MODULE:f1(stop), + ?MODULE:f2(j, k), + erlang:integer_to_list(id(3)), + ?MODULE:f3(l, m) + end, + fun (Tracee) -> + ?line 1 = + erlang:trace(Tracee, true, + [call,silent,return_to]), + ?line 1 = + erlang:trace_pattern( + {?MODULE,f2,2}, + [], + [global]), + ?line 1 = + erlang:trace_pattern( + {erlang,integer_to_list,1}, + [], + [global]), + ?line 1 = + erlang:trace_pattern( + {?MODULE,f1,1}, + [{[start],[],[{silent,false}]}, + {[stop],[],[{silent,true}]}], + [global]), + %% + %% Expected: (no return_to for global call trace) + %% + ?line + [{trace,Tracee,call,{?MODULE,f1,[start]}}, + {trace,Tracee,call,{?MODULE,f2,[f,g]}}, + {trace,Tracee,call,{erlang,integer_to_list,[2]}}, + {trace,Tracee,call,{?MODULE,f2,[h,i]}}] + end), + %% Local call trace + %% + %% Trace f2/2 and erlang:integer_to_list/1 without match spec + %% and use match spec on f1/1 to control silent flag. + ?line tr( + fun () -> + ?MODULE:f1(a), + ?MODULE:f2(b, c), + erlang:integer_to_list(id(1)), + ?MODULE:f3(d, e), + ?MODULE:f1(start), + ?MODULE:f2(f, g), + erlang:integer_to_list(id(2)), + ?MODULE:f3(h, i), + ?MODULE:f1(stop), + ?MODULE:f2(j, k), + erlang:integer_to_list(id(3)), + ?MODULE:f3(l, m) + end, + fun (Tracee) -> + ?line 1 = + erlang:trace(Tracee, true, + [call,silent,return_to]), + ?line 1 = + erlang:trace_pattern( + {?MODULE,f2,2}, + [], + [local]), + ?line 1 = + erlang:trace_pattern( + {erlang,integer_to_list,1}, + [], + [local]), + ?line 1 = + erlang:trace_pattern( + {?MODULE,f1,1}, + [{[start],[],[{silent,false}]}, + {[stop],[],[{silent,true}]}], + [local]), + %% + %% Expected: + %% + ?line + [{trace,Tracee,call,{?MODULE,f1,[start]}}, + {trace,Tracee,return_to, + {?MODULE,'-silent_no_ms/1-fun-2-',0}}, + {trace,Tracee,call,{?MODULE,f2,[f,g]}}, + {trace,Tracee,return_to, + {?MODULE,'-silent_no_ms/1-fun-2-',0}}, + {trace,Tracee,call,{erlang,integer_to_list,[2]}}, + {trace,Tracee,return_to, + {?MODULE,'-silent_no_ms/1-fun-2-',0}}, + {trace,Tracee,call,{?MODULE,f2,[h,i]}}, + {trace,Tracee,return_to,{?MODULE,f3,2}}] + end). + +ms_trace2(doc) -> + ["Test the match spec functions {trace/2}"]; +ms_trace2(suite) -> []; +ms_trace2(Config) when is_list(Config) -> + Tracer = self(), + %% Meta trace init + %% + %% Trace global f1/1, local f2/2, global erlang:integer_to_list/1 + %% without match spec. Use match spec functions + %% {trace/2} to control trace through fn/2,3. + ?line tr( + fun () -> + ?MODULE:f1(a), + ?MODULE:f2(b, c), + erlang:integer_to_list(id(1)), + ?MODULE:f3(d, e), + fn([all], [call,return_to,{tracer,Tracer}]), + ?MODULE:f1(f), + f2(g, h), + f1(i), + erlang:integer_to_list(id(2)), + ?MODULE:f3(j, k), + fn([call,return_to], []), + ?MODULE:f1(l), + ?MODULE:f2(m, n), + erlang:integer_to_list(id(3)), + ?MODULE:f3(o, p) + end, + fun (Tracee) -> + ?line 1 = + erlang:trace(Tracee, false, [all]), + ?line 1 = + erlang:trace_pattern( + {?MODULE,f1,1}, + [], + [global]), + ?line 1 = + erlang:trace_pattern( + {?MODULE,f2,2}, + [], + [local]), + ?line 1 = + erlang:trace_pattern( + {erlang,integer_to_list,1}, + [], + [global]), + ?line 3 = + erlang:trace_pattern( + {?MODULE,fn,'_'}, + [{['$1','$2'],[], + [{trace,'$1','$2'},{message,ms_trace2}]}], + [meta]), + %% + %% Expected: (no return_to for global call trace) + %% + ?line Origin = {match_spec_SUITE,'-ms_trace2/1-fun-0-',1}, + ?line + [{trace_ts,Tracee,call, + {?MODULE,fn, + [[all],[call,return_to,{tracer,Tracer}]]}, + ms_trace2}, + {trace,Tracee,call,{?MODULE,f1,[f]}}, + {trace,Tracee,call,{?MODULE,f2,[g,h]}}, + {trace,Tracee,return_to,Origin}, + {trace,Tracee,call,{erlang,integer_to_list,[2]}}, + {trace,Tracee,call,{?MODULE,f2,[j,k]}}, + {trace,Tracee,return_to,{?MODULE,f3,2}}, + {trace_ts,Tracee,call, + {?MODULE,fn, + [[call,return_to],[]]}, + ms_trace2}] + end), + ok. + + + +ms_trace3(doc) -> + ["Test the match spec functions {trace/3}"]; +ms_trace3(suite) -> []; +ms_trace3(Config) when is_list(Config) -> + TraceeName = 'match_spec_SUITE:ms_trace3', + Tracer = self(), + %% Meta trace init + %% + %% Trace global f1/1, local f2/2, global erlang:integer_to_list/1 + %% without match spec. Use match spec functions + %% {trace/2} to control trace through fn/2,3. + Tag = make_ref(), + Controller = + spawn_link( + fun () -> + receive + {Tracee,Tag,start} -> + fn(TraceeName, [all], + [call,return_to,send,'receive', + {tracer,Tracer}]), + Tracee ! {self(),Tag,started}, + receive {Tracee,Tag,stop_1} -> ok end, + fn(Tracee, [call,return_to], []), + Tracee ! {self(),Tag,stopped_1}, + receive {Tracee,Tag,stop_2} -> ok end, + fn(Tracee, [all], []), + Tracee ! {self(),Tag,stopped_2} + end + end), + ?line tr( + fun () -> %% Action + register(TraceeName, self()), + ?MODULE:f1(a), + ?MODULE:f2(b, c), + erlang:integer_to_list(id(1)), + ?MODULE:f3(d, e), + Controller ! {self(),Tag,start}, + receive {Controller,Tag,started} -> ok end, + ?MODULE:f1(f), + f2(g, h), + f1(i), + erlang:integer_to_list(id(2)), + ?MODULE:f3(j, k), + Controller ! {self(),Tag,stop_1}, + receive {Controller,Tag,stopped_1} -> ok end, + ?MODULE:f1(l), + ?MODULE:f2(m, n), + erlang:integer_to_list(id(3)), + ?MODULE:f3(o, p), + Controller ! {self(),Tag,stop_2}, + receive {Controller,Tag,stopped_2} -> ok end, + ?MODULE:f1(q), + ?MODULE:f2(r, s), + erlang:integer_to_list(id(4)), + ?MODULE:f3(t, u) + end, + + fun (Tracee) -> %% Startup + ?line 1 = + erlang:trace(Tracee, false, [all]), + ?line 1 = + erlang:trace_pattern( + {?MODULE,f1,1}, + [], + [global]), + ?line 1 = + erlang:trace_pattern( + {?MODULE,f2,2}, + [], + [local]), + ?line 1 = + erlang:trace_pattern( + {erlang,integer_to_list,1}, + [], + [global]), + ?line 3 = + erlang:trace_pattern( + {?MODULE,fn,'_'}, + [{['$1','$2','$3'],[], + [{trace,'$1','$2','$3'},{message,Tag}]}], + [meta]), + %% + %% Expected: (no return_to for global call trace) + %% + ?line Origin = {match_spec_SUITE,'-ms_trace3/1-fun-1-',2}, + ?line + [{trace_ts,Controller,call, + {?MODULE,fn,[TraceeName,[all], + [call,return_to,send,'receive', + {tracer,Tracer}]]}, + Tag}, + {trace,Tracee,'receive',{Controller,Tag,started}}, + {trace,Tracee,call,{?MODULE,f1,[f]}}, + {trace,Tracee,call,{?MODULE,f2,[g,h]}}, + {trace,Tracee,return_to,Origin}, + {trace,Tracee,call,{erlang,integer_to_list,[2]}}, + {trace,Tracee,call,{?MODULE,f2,[j,k]}}, + {trace,Tracee,return_to,{?MODULE,f3,2}}, + {trace,Tracee,send,{Tracee,Tag,stop_1},Controller}, + {trace_ts,Controller,call, + {?MODULE,fn,[Tracee,[call,return_to],[]]}, + Tag}, + {trace_ts,Controller,call, + {?MODULE,fn,[Tracee,[all],[]]}, + Tag}] + end), + ok. + + + +destructive_in_test_bif(doc) -> + ["Test that destructive operations in test bif does not really happen"]; +destructive_in_test_bif(suite) -> []; +destructive_in_test_bif(Config) when is_list(Config) -> + ?line {ok,OldToken,_,_} = erlang:match_spec_test + ([], + [{'_',[],[{message,{get_seq_token}}]}],trace), + ?line {ok,_,_,_} = erlang:match_spec_test + ([], + [{'_',[],[{message,{set_seq_token, label, 1}}]}], + trace), + ?line {ok,OldToken,_,_} = erlang:match_spec_test + ([], + [{'_',[],[{message,{get_seq_token}}]}],trace), + ?line {ok, OldTCW,_,_} = erlang:match_spec_test + ([],[{'_',[],[{message,{get_tcw}}]}],trace), + ?line {ok,OldTCW,_,_} = erlang:match_spec_test + ([], + [{'_',[],[{message,{set_tcw, OldTCW+1}}]}], + trace), + ?line {ok, OldTCW,_,_} = erlang:match_spec_test + ([],[{'_',[],[{message,{get_tcw}}]}],trace), + ok. + +boxed_and_small(doc) -> + ["Test that the comparision between boxed and small does not crash emulator"]; +boxed_and_small(suite) -> []; +boxed_and_small(Config) when is_list(Config) -> + ?line {ok, Node} = start_node(match_spec_suite_other), + ?line ok = rpc:call(Node,?MODULE,do_boxed_and_small,[]), + ?line stop_node(Node), + ok. + +do_boxed_and_small() -> + {ok, false, _, _} = erlang:match_spec_test({0,3},[{{1.47,'_'},[],['$_']}],table), + {ok, false, _, _} = erlang:match_spec_test({0,3},[{{12345678901234567890,'_'},[],['$_']}],table), + {ok, false, _, _} = erlang:match_spec_test({0,3},[{{<<1,2,3,4>>,'_'},[],['$_']}],table), + {ok, false, _, _} = erlang:match_spec_test({0,3},[{{make_ref(),'_'},[],['$_']}],table), + ok. + +errchk(Pat) -> + case catch erlang:trace_pattern({?MODULE, f2, 2}, Pat) of + {'EXIT', {badarg, _}} -> + ok; + Other -> + test_server:fail({noerror, Other}) + end. + +unary_minus(suite) -> + []; +unary_minus(doc) -> + ["Checks that unary minus works"]; +unary_minus(Config) when is_list(Config) -> + ?line {ok,true,[],[]} = erlang:match_spec_test + (5, + [{'$1', + [{'<',{'-','$1'},-4}], + [true]}], + table), + ?line {ok,false,[],[]} = erlang:match_spec_test + (5, + [{'$1', + [{'<',{'-','$1'},-6}], + [true]}], + table), + ?line {ok,true,[],[]} = erlang:match_spec_test + (5, + [{'$1', + [{'=:=',{'-','$1',2},3}], + [true]}], + table), + ?line {ok,false,[],[]} = erlang:match_spec_test + (hej, + [{'$1', + [{'=/=',{'-','$1'},0}], + [true]}], + table), + ok. +unary_plus(suite) -> + []; +unary_plus(doc) -> + ["Checks that unary plus works"]; +unary_plus(Config) when is_list(Config) -> + ?line {ok,true,[],[]} = erlang:match_spec_test + (5, + [{'$1', + [{'<',{'+','$1'},6}], + [true]}], + table), + ?line {ok,false,[],[]} = erlang:match_spec_test + (5, + [{'$1', + [{'<',{'+','$1'},4}], + [true]}], + table), + ?line {ok,true,[],[]} = erlang:match_spec_test + (5, + [{'$1', + [{'=:=',{'+','$1',2},7}], + [true]}], + table), + ?line {ok,false,[],[]} = erlang:match_spec_test + (hej, + [{'$1', + [{'=/=',{'+','$1'},0}], + [true]}], + table), + ok. + + + + +guard_exceptions(suite) -> + []; +guard_exceptions(doc) -> + ["Checks that exceptions in guards are handled correctly"]; +guard_exceptions(Config) when is_list(Config) -> + ?line {ok,false,[],[]} = erlang:match_spec_test + (5, + [{'$1', + [{'or',{is_integer,'$1'},{'or','$1','$1'}}], + [true]}], + table), + ?line {ok,true,[],[]} = erlang:match_spec_test + (5, + [{'$1', + [{'orelse',{is_integer,'$1'}, + {'or','$1','$1'}}], + [true]}], + table), + ?line {ok,false,[],[]} = erlang:match_spec_test + (5, + [{'$1', + [{'orelse',{'or','$1',true}, + {is_integer,'$1'}}], + [true]}], + table), + ?line {ok,false,[],[]} = erlang:match_spec_test + (5, + [{'$1', + [{'or',{is_integer,'$1'}, + {'orelse','$1',true}}], + [true]}], + table), + ?line {ok,true,[],[]} = erlang:match_spec_test + (5, + [{'$1', + [{'or',{is_integer,'$1'}, + {'orelse',true,'$1'}}], + [true]}], + table), + ?line {ok,true,[],[]} = erlang:match_spec_test + (5, + [{'$1', + [{'or',{is_integer,'$1'}, + {'andalso',false,'$1'}}], + [true]}], + table), + ?line {ok,false,[],[]} = erlang:match_spec_test + (5, + [{'$1', + [{'or',{is_integer,'$1'}, + {'andalso','$1',false}}], + [true]}], + table), + + ?line {ok,false,[],[]} = erlang:match_spec_test + (5, + [{'$1', + [{'or',{is_integer,'$1'}, + {'andalso','$1',false}}], + [true]}], + table), + + ok. + +fpe(suite) -> + []; +fpe(doc) -> + ["Checks floating point exceptions in match-specs"]; +fpe(Config) when is_list(Config) -> + MS = [{{'$1'},[],[{'/','$1',0}]}], + case catch (['EXIT','EXIT'] = + ets:match_spec_run([{1},{2}],ets:match_spec_compile(MS))) of + {'EXIT',_} -> test_server:fail({error, + "Floating point exceptions faulty"}); + _ -> ok + end. + +moving_labels(Config) when is_list(Config) -> + %% Force an andalso/orelse construction to be moved by placing it + %% in a tuple followed by a constant term. Labels should still + %% point at their correct target. + %% + Ms = [{{'$1','$2'},[],[{{ok,{'andalso','$1','$2'},[1,2,3]}}]}], + ?line {ok,{ok,false,[1,2,3]},[],[]} = + erlang:match_spec_test({true,false}, Ms, table), + + Ms2 = [{{'$1','$2'},[],[{{ok,{'orelse','$1','$2'},[1,2,3]}}]}], + ?line {ok,{ok,true,[1,2,3]},[],[]} = + erlang:match_spec_test({true,false}, Ms2, table), + + ok. + +tr(Fun, MFA, Pat, Expected) -> + tr(Fun, MFA, [call], Pat, [global], Expected). + +tr(Fun, MFA, TraceFlags, Pat, PatFlags, Expected0) -> + tr(Fun, + fun(P) -> + erlang:trace(P, true, TraceFlags), + erlang:trace_pattern(MFA, Pat, PatFlags), + lists:map( + fun(X) -> + list_to_tuple([trace, P | tuple_to_list(X)]) + end, + Expected0) + end). + +tr(RunFun, ControlFun) -> + P = spawn(?MODULE, runner, [self(), RunFun]), + collect(P, ControlFun(P)). + +collect(P, TMs) -> + start_collect(P), + collect(TMs), + stop_collect(P). + +collect([]) -> + receive + M -> + ?t:format("Got unexpected: ~p~n", [M]), + flush({got_unexpected,M}) + after 17 -> + ok + end; +collect([TM | TMs]) -> + ?t:format( "Expecting: ~p~n", [TM]), + receive + M -> + case if element(1, M) == trace_ts -> + list_to_tuple(lists:reverse( + tl(lists:reverse(tuple_to_list(M))))); + true -> M + end of + TM -> + ?t:format("Got: ~p~n", [M]), + collect(TMs); + _ -> + ?t:format("Got unexpected: ~p~n", [M]), + flush({got_unexpected,M}) + end + end. + +flush(Reason) -> + receive + M -> + ?t:format("In queue: ~p~n", [M]), + flush(Reason) + after 17 -> + ?t:fail(Reason) + end. + +start_collect(P) -> + P ! {go, self()}. + +stop_collect(P) -> + P ! {done, self()}, + receive + {gone, P} -> + ok + end. + + +runner(Collector, Fun) -> + receive + {go, Collector} -> + go + end, + Fun(), + receive + {done, Collector} -> + Collector ! {gone, self()} + end. + +f1(X) -> + {X}. + +f2(X, Y) -> + {X, Y}. + +f3(X,Y) -> + ?MODULE:f2(X,Y), + ok. + +fn(X) -> + [X]. +fn(X, Y) -> + [X, Y]. +fn(X, Y, Z) -> + [X, Y, Z]. + +id(X) -> + X. + +start_node(Name) -> + Pa = filename:dirname(code:which(?MODULE)), + Cookie = atom_to_list(erlang:get_cookie()), + test_server:start_node(Name, slave, + [{args, "-setcookie " ++ Cookie ++" -pa " ++ Pa}]). + +stop_node(Node) -> + test_server:stop_node(Node). diff --git a/erts/emulator/test/module_info_SUITE.erl b/erts/emulator/test/module_info_SUITE.erl new file mode 100644 index 0000000000..f34a2b496c --- /dev/null +++ b/erts/emulator/test/module_info_SUITE.erl @@ -0,0 +1,105 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(module_info_SUITE). + +-include("test_server.hrl"). + +-export([all/1,init_per_testcase/2,end_per_testcase/2, + exports/1,functions/1,native/1]). + +%%-compile(native). + +%% Helper. +-export([native_proj/1,native_filter/1]). + +all(suite) -> + [exports,functions,native]. + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog = ?t:timetrap(?t:minutes(3)), + [{watchdog,Dog}|Config]. + +end_per_testcase(_Func, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +%% Should return all functions exported from this module. (local) +all_exported() -> + All = add_arity(all(suite)), + lists:sort([{all,1},{init_per_testcase,2},{end_per_testcase,2}, + {module_info,0},{module_info,1},{native_proj,1}, + {native_filter,1}|All]). + +%% Should return all functions in this module. (local) +all_functions() -> + Locals = [{add_arity,1},{add_arity,2},{all_exported,0},{all_functions,0}], + lists:sort(Locals++all_exported()). + +%% Test that the list of exported functions from this module is correct. +exports(Config) when is_list(Config) -> + ?line All = all_exported(), + ?line All = lists:sort(?MODULE:module_info(exports)), + ?line (catch ?MODULE:foo()), + ?line All = lists:sort(?MODULE:module_info(exports)), + ok. + +%% Test that the list of exported functions from this module is correct. +functions(Config) when is_list(Config) -> + ?line All = all_functions(), + ?line All = lists:sort(?MODULE:module_info(functions)), + ok. + +%% Test that the list of exported functions from this module is correct. +native(Config) when is_list(Config) -> + ?line All = all_functions(), + ?line case ?MODULE:module_info(native_addresses) of + [] -> + {comment,"no native functions"}; + L -> + %% Verify that all functions have unique addresses. + ?line S0 = sofs:set(L, [{name,arity,addr}]), + ?line S1 = sofs:projection({external,fun ?MODULE:native_proj/1}, S0), + ?line S2 = sofs:relation_to_family(S1), + ?line S3 = sofs:family_specification(fun ?MODULE:native_filter/1, S2), + ?line 0 = sofs:no_elements(S3), + ?line S4 = sofs:range(S1), + + %% Verify that the set of function with native addresses + %% is a subset of all functions in the module. + ?line AllSet = sofs:set(All, [{name,arity}]), + ?line true = sofs:is_subset(S4, AllSet), + + {comment,integer_to_list(sofs:no_elements(S0))++" native functions"} + end. + +native_proj({Name,Arity,Addr}) -> + {Addr,{Name,Arity}}. + +native_filter(Set) -> + sofs:no_elements(Set) =/= 1. + +%% Helper functions (local). + +add_arity(L) -> + add_arity(L, []). + +add_arity([H|T], Acc) -> + add_arity(T, [{H,1}|Acc]); +add_arity([], Acc) -> lists:reverse(Acc). diff --git a/erts/emulator/test/monitor_SUITE.erl b/erts/emulator/test/monitor_SUITE.erl new file mode 100644 index 0000000000..68e378dfec --- /dev/null +++ b/erts/emulator/test/monitor_SUITE.erl @@ -0,0 +1,943 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(monitor_SUITE). + +-include("test_server.hrl"). + +-export([all/1, + case_1/1, case_1a/1, case_2/1, case_2a/1, mon_e_1/1, demon_e_1/1, demon_1/1, + demon_2/1, demon_3/1, demonitor_flush/1, remove_monitor/1, + local_remove_monitor/1, remote_remove_monitor/1, mon_1/1, mon_2/1, + large_exit/1, list_cleanup/1, mixer/1, named_down/1, otp_5827/1]). + +-export([init_per_testcase/2, fin_per_testcase/2]). + +-export([y2/1, g/1, g0/0, g1/0, large_exit_sub/1]). + +all(suite) -> + [case_1, case_1a, case_2, case_2a, mon_e_1, demon_e_1, demon_1, mon_1, + mon_2, demon_2, demon_3, demonitor_flush, remove_monitor, + large_exit, list_cleanup, mixer, named_down, + otp_5827]. + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog=?t:timetrap(?t:minutes(15)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +case_1(doc) -> + "A monitors B, B kills A and then exits (yielded core dump)"; +case_1(suite) -> []; +case_1(Config) when is_list(Config) -> + ?line process_flag(trap_exit, true), + ?line spawn_link(?MODULE, g0, []), + ?line receive _ -> ok end, + ok. + +case_1a(doc) -> + "A monitors B, B kills A and then exits (yielded core dump)"; +case_1a(Config) when is_list(Config) -> + ?line process_flag(trap_exit, true), + ?line spawn_link(?MODULE, g1, []), + ?line receive _ -> ok end, + ok. + +g0() -> + ?line B = spawn(?MODULE, g, [self()]), + ?line erlang:monitor(process, B), + ?line B ! ok, + ?line receive ok -> ok end, + ok. + +g1() -> + ?line {B,_} = spawn_monitor(?MODULE, g, [self()]), + ?line B ! ok, + ?line receive ok -> ok end, + ok. + +g(Parent) -> + ?line receive ok -> ok end, + ?line exit(Parent, foo), + ?line ok. + + +case_2(doc) -> + "A monitors B, B demonitors A (yielded core dump)"; +case_2(Config) when is_list(Config) -> + ?line B = spawn(?MODULE, y2, [self()]), + ?line R = erlang:monitor(process, B), + ?line B ! R, + ?line receive + {'EXIT', _} -> ok; + Other -> + test_server:fail({rec, Other}) + end, + ?line expect_down(R, B, normal), + ok. + +case_2a(doc) -> + "A monitors B, B demonitors A (yielded core dump)"; +case_2a(Config) when is_list(Config) -> + ?line {B,R} = spawn_monitor(?MODULE, y2, [self()]), + ?line B ! R, + ?line receive + {'EXIT', _} -> ok; + Other -> + test_server:fail({rec, Other}) + end, + ?line expect_down(R, B, normal), + ok. + +y2(Parent) -> + ?line R = receive T -> T end, + ?line Parent ! (catch erlang:demonitor(R)), + ok. + +expect_down(Ref, P) -> + receive + {'DOWN', Ref, process, P, Reason} -> + Reason; + Other -> + test_server:fail({rec, Other}) + end. + +expect_down(Ref, P, Reason) -> + receive + {'DOWN', Ref, process, P, Reason} -> + ok; + Other -> + test_server:fail({rec, Other}) + end. + +expect_no_msg() -> + receive + Msg -> + test_server:fail({msg, Msg}) + after 0 -> + ok + end. + +%%% Error cases for monitor/2 + +mon_e_1(doc) -> + "Error cases for monitor/2"; +mon_e_1(suite) -> []; +mon_e_1(Config) when is_list(Config) -> + ?line {ok, N} = test_server:start_node(hej, slave, []), + ?line mon_error(plutt, self()), + ?line mon_error(process, [bingo]), + ?line mon_error(process, {rex, N, junk}), + ?line mon_error(process, 1), + + ?line true = test_server:stop_node(N), + ok. + +%%% We would also like to have a test case that tries to monitor something +%%% on an R5 node, but this isn't possible to do systematically. +%%% +%%% Likewise against an R6 node, which is not capable of monitoring +%%% by name, which gives a badarg on the R7 node at the call to +%%% erlang:monitor(process, {Name, Node}). This has been tested +%%% manually at least once. + +mon_error(Type, Item) -> + case catch erlang:monitor(Type, Item) of + {'EXIT', _} -> + ok; + Other -> + test_server:fail({err, Other}) + end. + +%%% Error cases for demonitor/1 + +demon_e_1(doc) -> + "Error cases for demonitor/1"; +demon_e_1(suite) -> []; +demon_e_1(Config) when is_list(Config) -> + ?line {ok, N} = test_server:start_node(hej, slave, []), + ?line demon_error(plutt, badarg), + ?line demon_error(1, badarg), + + %% Demonitor with ref created at other node + ?line R1 = rpc:call(N, erlang, make_ref, []), + ?line demon_error(R1, badarg), + + %% Demonitor with ref created at wrong monitor link end + ?line P0 = self(), + ?line P2 = spawn( + fun() -> + P0 ! {self(), ref, erlang:monitor(process,P0)}, + receive {P0, stop} -> ok end + end ), + ?line receive + {P2, ref, R2} -> + ?line demon_error(R2, badarg), + ?line P2 ! {self(), stop}; + Other2 -> + test_server:fail({rec, Other2}) + end, + + ?line true = test_server:stop_node(N), + ok. + +demon_error(Ref, Reason) -> + case catch erlang:demonitor(Ref) of + {'EXIT', {Reason, _}} -> + ok; + Other -> + test_server:fail({err, Other}) + end. + +%%% No-op cases for demonitor/1 + +demon_1(doc) -> + "demonitor/1"; +demon_1(suite) -> []; +demon_1(Config) when is_list(Config) -> + ?line true = erlang:demonitor(make_ref()), + ok. + + +%%% Cases for demonitor/1 + +demon_2(doc) -> + "Cases for demonitor/1"; +demon_2(suite) -> []; +demon_2(Config) when is_list(Config) -> + ?line R1 = erlang:monitor(process, self()), + ?line true = erlang:demonitor(R1), + %% Extra demonitor + ?line true = erlang:demonitor(R1), + ?line expect_no_msg(), + + %% Normal 'DOWN' + ?line P2 = spawn(timer, sleep, [1]), + ?line R2 = erlang:monitor(process, P2), + ?line case expect_down(R2, P2) of + normal -> ?line ok; + noproc -> ?line ok; + BadReason -> ?line ?t:fail({bad_reason, BadReason}) + end, + +%% OTP-5772 +% %% 'DOWN' before demonitor +% ?line P3 = spawn(timer, sleep, [100000]), +% ?line R3 = erlang:monitor(process, P3), +% ?line exit(P3, frop), +% ?line erlang:demonitor(R3), +% ?line expect_down(R3, P3, frop), + + %% Demonitor before 'DOWN' + ?line P4 = spawn(timer, sleep, [100000]), + ?line R4 = erlang:monitor(process, P4), + ?line erlang:demonitor(R4), + ?line exit(P4, frop), + ?line expect_no_msg(), + + ok. + +demon_3(doc) -> + "Distributed case for demonitor/1 (OTP-3499)"; +demon_3(suite) -> []; +demon_3(Config) when is_list(Config) -> + ?line {ok, N} = test_server:start_node(hej, slave, []), + + %% 'DOWN' before demonitor + ?line P2 = spawn(N, timer, sleep, [100000]), + ?line R2 = erlang:monitor(process, P2), + ?line true = test_server:stop_node(N), + ?line true = erlang:demonitor(R2), + ?line expect_down(R2, P2, noconnection), + + ?line {ok, N2} = test_server:start_node(hej, slave, []), + + %% Demonitor before 'DOWN' + ?line P3 = spawn(N2, timer, sleep, [100000]), + ?line R3 = erlang:monitor(process, P3), + ?line true = erlang:demonitor(R3), + ?line true = test_server:stop_node(N2), + ?line expect_no_msg(), + + ok. + +demonitor_flush(suite) -> []; +demonitor_flush(doc) -> []; +demonitor_flush(Config) when is_list(Config) -> + ?line {'EXIT', {badarg, _}} = (catch erlang:demonitor(make_ref(), flush)), + ?line {'EXIT', {badarg, _}} = (catch erlang:demonitor(make_ref(), [flus])), + ?line {'EXIT', {badarg, _}} = (catch erlang:demonitor(x, [flush])), + ?line {ok, N} = test_server:start_node(demonitor_flush, slave, []), + ?line ok = demonitor_flush_test(N), + ?line true = test_server:stop_node(N), + ?line ok = demonitor_flush_test(node()). + +demonitor_flush_test(Node) -> + ?line P = spawn(Node, timer, sleep, [100000]), + ?line M1 = erlang:monitor(process, P), + ?line M2 = erlang:monitor(process, P), + ?line M3 = erlang:monitor(process, P), + ?line M4 = erlang:monitor(process, P), + ?line true = erlang:demonitor(M1, [flush, flush]), + ?line exit(P, bang), + ?line receive {'DOWN', M2, process, P, bang} -> ok end, + ?line receive after 100 -> ok end, + ?line true = erlang:demonitor(M3, [flush]), + ?line true = erlang:demonitor(M4, []), + ?line receive {'DOWN', M4, process, P, bang} -> ok end, + ?line receive + {'DOWN', M, _, _, _} =DM when M == M1, + M == M3 -> + ?line ?t:fail({unexpected_down_message, DM}) + after 100 -> + ?line ok + end. + +-define(RM_MON_GROUPS, 100). +-define(RM_MON_GPROCS, 100). + +remove_monitor(suite) -> + [local_remove_monitor, remote_remove_monitor]. + +local_remove_monitor(Config) when is_list(Config) -> + Gs = generate(fun () -> start_remove_monitor_group(node()) end, + ?RM_MON_GROUPS), + {True, False} = lists:foldl(fun (G, {T, F}) -> + receive + {rm_mon_res, G, {GT, GF}} -> + {T+GT, F+GF} + end + end, + {0, 0}, + Gs), + erlang:display({local_remove_monitor, True, False}), + {comment, + "True = "++integer_to_list(True)++"; False = "++integer_to_list(False)}. + +remote_remove_monitor(Config) when is_list(Config) -> + ?line {ok, N} = test_server:start_node(demonitor_flush, slave, []), + Gs = generate(fun () -> start_remove_monitor_group(node()) end, + ?RM_MON_GROUPS), + {True, False} = lists:foldl(fun (G, {T, F}) -> + receive + {rm_mon_res, G, {GT, GF}} -> + {T+GT, F+GF} + end + end, + {0, 0}, + Gs), + erlang:display({remote_remove_monitor, True, False}), + ?line true = test_server:stop_node(N), + {comment, + "True = "++integer_to_list(True)++"; False = "++integer_to_list(False)}. + +start_remove_monitor_group(Node) -> + Master = self(), + spawn_link( + fun () -> + Ms = generate(fun () -> + P = spawn(Node, fun () -> ok end), + erlang:monitor(process, P) + end, ?RM_MON_GPROCS), + Res = lists:foldl(fun (M, {T, F}) -> + case erlang:demonitor(M, [info]) of + true -> + receive + {'DOWN', M, _, _, _} -> + exit(down_msg_found) + after 0 -> + ok + end, + {T+1, F}; + false -> + receive + {'DOWN', M, _, _, _} -> + ok + after 0 -> + exit(no_down_msg_found) + end, + {T, F+1} + end + end, + {0,0}, + Ms), + Master ! {rm_mon_res, self(), Res} + end). + + +%%% Cases for monitor/2 + +mon_1(doc) -> + "Cases for monitor/2"; +mon_1(suite) -> []; +mon_1(Config) when is_list(Config) -> + %% Normal case + ?line P2 = spawn(timer, sleep, [1]), + ?line R2 = erlang:monitor(process, P2), + ?line case expect_down(R2, P2) of + normal -> ?line ok; + noproc -> ?line ok; + BadReason -> ?line ?t:fail({bad_reason, BadReason}) + end, + ?line {P2A,R2A} = spawn_monitor(timer, sleep, [1]), + ?line expect_down(R2A, P2A, normal), + + %% 'DOWN' with other reason + ?line P3 = spawn(timer, sleep, [100000]), + ?line R3 = erlang:monitor(process, P3), + ?line exit(P3, frop), + ?line expect_down(R3, P3, frop), + ?line {P3A,R3A} = spawn_monitor(timer, sleep, [100000]), + ?line exit(P3A, frop), + ?line expect_down(R3A, P3A, frop), + + %% Monitor fails because process is dead + ?line R4 = erlang:monitor(process, P3), + ?line expect_down(R4, P3, noproc), + + %% Normal case (named process) + ?line P5 = start_jeeves(jeeves), + ?line R5 = erlang:monitor(process, jeeves), + ?line tell_jeeves(P5, stop), + ?line expect_down(R5, {jeeves, node()}, normal), + + %% 'DOWN' with other reason and node explicit activation + ?line P6 = start_jeeves(jeeves), + ?line R6 = erlang:monitor(process, {jeeves, node()}), + ?line tell_jeeves(P6, {exit, frop}), + ?line expect_down(R6, {jeeves, node()}, frop), + + %% Monitor (named process) fails because process is dead + ?line R7 = erlang:monitor(process, {jeeves, node()}), + ?line expect_down(R7, {jeeves, node()}, noproc), + + ok. + +mon_2(doc) -> + "Distributed cases for monitor/2"; +mon_2(suite) -> []; +mon_2(Config) when is_list(Config) -> + ?line {ok, N1} = test_server:start_node(hej1, slave, []), + + %% Normal case + ?line P2 = spawn(N1, timer, sleep, [4000]), + ?line R2 = erlang:monitor(process, P2), + ?line expect_down(R2, P2, normal), + + %% 'DOWN' with other reason + ?line P3 = spawn(N1, timer, sleep, [100000]), + ?line R3 = erlang:monitor(process, P3), + ?line exit(P3, frop), + ?line expect_down(R3, P3, frop), + + %% Monitor fails because process is dead + ?line R4 = erlang:monitor(process, P3), + ?line expect_down(R4, P3, noproc), + + %% Other node goes down + ?line P5 = spawn(N1, timer, sleep, [100000]), + ?line R5 = erlang:monitor(process, P5), + + ?line true = test_server:stop_node(N1), + + ?line expect_down(R5, P5, noconnection), + + %% Monitor fails because other node is dead + ?line P6 = spawn(N1, timer, sleep, [100000]), + ?line R6 = erlang:monitor(process, P6), + ?line R6_Reason = expect_down(R6, P6), + ?line true = (R6_Reason == noconnection) orelse (R6_Reason == noproc), + + %% Start a new node that can load code in this module + ?line PA = filename:dirname(code:which(?MODULE)), + ?line {ok, N2} = test_server:start_node + (hej2, slave, [{args, "-pa " ++ PA}]), + + %% Normal case (named process) + ?line P7 = start_jeeves({jeeves, N2}), + ?line R7 = erlang:monitor(process, {jeeves, N2}), + ?line tell_jeeves(P7, stop), + ?line expect_down(R7, {jeeves, N2}, normal), + + %% 'DOWN' with other reason (named process) + ?line P8 = start_jeeves({jeeves, N2}), + ?line R8 = erlang:monitor(process, {jeeves, N2}), + ?line tell_jeeves(P8, {exit, frop}), + ?line expect_down(R8, {jeeves, N2}, frop), + + %% Monitor (named process) fails because process is dead + ?line R9 = erlang:monitor(process, {jeeves, N2}), + ?line expect_down(R9, {jeeves, N2}, noproc), + + %% Other node goes down (named process) + ?line _P10 = start_jeeves({jeeves, N2}), + ?line R10 = erlang:monitor(process, {jeeves, N2}), + + ?line true = test_server:stop_node(N2), + + ?line expect_down(R10, {jeeves, N2}, noconnection), + + %% Monitor (named process) fails because other node is dead + ?line R11 = erlang:monitor(process, {jeeves, N2}), + ?line expect_down(R11, {jeeves, N2}, noconnection), + + ok. + +%%% Large exit reason. Crashed first attempt to release R5B. + +large_exit(doc) -> + "Large exit reason"; +large_exit(suite) -> []; +large_exit(Config) when is_list(Config) -> + ?line f(100), + ok. + +f(0) -> + ok; +f(N) -> + f(), + f(N-1). + +f() -> + ?line S0 = {big, tuple, with, [list, 4563784278]}, + ?line S = {S0, term_to_binary(S0)}, + ?line P = spawn(?MODULE, large_exit_sub, [S]), + ?line R = erlang:monitor(process, P), + ?line P ! hej, + receive + {'DOWN', R, process, P, X} -> + ?line io:format(" -> ~p~n", [X]), + if + X == S -> + ok; + true -> + test_server:fail({X, S}) + end; + Other -> + ?line io:format(" -> ~p~n", [Other]), + exit({answer, Other}) + end. + +large_exit_sub(S) -> + receive _X -> ok end, + exit(S). + +%%% Testing of monitor link list cleanup +%%% by using erlang:process_info(self(), monitors) +%%% and erlang:process_info(self(), monitored_by) + +list_cleanup(doc) -> + "Testing of monitor link list cleanup by using " ++ + "erlang:process_info/2"; +list_cleanup(suite) -> []; +list_cleanup(Config) when is_list(Config) -> + ?line P0 = self(), + ?line M = node(), + ?line PA = filename:dirname(code:which(?MODULE)), + ?line true = register(master_bertie, self()), + + %% Normal local case, monitor and demonitor + ?line P1 = start_jeeves(jeeves), + ?line {[], []} = monitors(), + ?line expect_jeeves(P1, monitors, {monitors, {[], []}}), + ?line R1a = erlang:monitor(process, P1), + ?line {[{process, P1}], []} = monitors(), + ?line expect_jeeves(P1, monitors, {monitors, {[], [P0]}}), + ?line true = erlang:demonitor(R1a), + ?line expect_no_msg(), + ?line {[], []} = monitors(), + ?line expect_jeeves(P1, monitors, {monitors, {[], []}}), + %% Remonitor named and try again, now exiting the monitored process + ?line R1b = erlang:monitor(process, jeeves), + ?line {[{process, {jeeves, M}}], []} = monitors(), + ?line expect_jeeves(P1, monitors, {monitors, {[], [P0]}}), + ?line tell_jeeves(P1, stop), + ?line expect_down(R1b, {jeeves, node()}, normal), + ?line {[], []} = monitors(), + + %% Slightly weird local case - the monitoring process crashes + ?line P2 = start_jeeves(jeeves), + ?line {[], []} = monitors(), + ?line expect_jeeves(P2, monitors, {monitors, {[], []}}), + ?line {monitor_process, _R2} = + ask_jeeves(P2, {monitor_process, master_bertie}), + ?line {[], [P2]} = monitors(), + ?line expect_jeeves(P2, monitors, + {monitors, {[{process, {master_bertie, node()}}], []}}), + ?line tell_jeeves(P2, {exit, frop}), + timer:sleep(2000), + ?line {[], []} = monitors(), + + %% Start a new node that can load code in this module + ?line {ok, J} = test_server:start_node + (jeeves, slave, [{args, "-pa " ++ PA}]), + + %% Normal remote case, monitor and demonitor + ?line P3 = start_jeeves({jeeves, J}), + ?line {[], []} = monitors(), + ?line expect_jeeves(P3, monitors, {monitors, {[], []}}), + ?line R3a = erlang:monitor(process, P3), + ?line {[{process, P3}], []} = monitors(), + ?line expect_jeeves(P3, monitors, {monitors, {[], [P0]}}), + ?line true = erlang:demonitor(R3a), + ?line expect_no_msg(), + ?line {[], []} = monitors(), + ?line expect_jeeves(P3, monitors, {monitors, {[], []}}), + %% Remonitor named and try again, now exiting the monitored process + ?line R3b = erlang:monitor(process, {jeeves, J}), + ?line {[{process, {jeeves, J}}], []} = monitors(), + ?line expect_jeeves(P3, monitors, {monitors, {[], [P0]}}), + ?line tell_jeeves(P3, stop), + ?line expect_down(R3b, {jeeves, J}, normal), + ?line {[], []} = monitors(), + + %% Slightly weird remote case - the monitoring process crashes + ?line P4 = start_jeeves({jeeves, J}), + ?line {[], []} = monitors(), + ?line expect_jeeves(P4, monitors, {monitors, {[], []}}), + ?line {monitor_process, _R4} = + ask_jeeves(P4, {monitor_process, {master_bertie, M}}), + ?line {[], [P4]} = monitors(), + ?line expect_jeeves(P4, monitors, + {monitors, {[{process, {master_bertie, M}}], []}} ), + ?line tell_jeeves(P4, {exit, frop}), + timer:sleep(2000), + ?line {[], []} = monitors(), + + %% Now, the monitoring remote node crashes + ?line P5 = start_jeeves({jeeves, J}), + ?line {[], []} = monitors(), + ?line expect_jeeves(P5, monitors, {monitors, {[], []}}), + ?line {monitor_process, _R5} = + ask_jeeves(P5, {monitor_process, P0}), + ?line {[], [P5]} = monitors(), + ?line expect_jeeves(P5, monitors, + {monitors, {[{process, P0}], []}} ), + ?line test_server:stop_node(J), + timer:sleep(4000), + ?line {[], []} = monitors(), + + ?line true = unregister(master_bertie), + ok. + + +%%% Mixed internal and external monitors + +mixer(doc) -> + "Test mixing of internal and external monitors."; +mixer(Config) when is_list(Config) -> + ?line PA = filename:dirname(code:which(?MODULE)), + ?line NN = [j0,j1,j2,j3], +% ?line NN = [j0,j1], + ?line NL0 = [begin + {ok, J} = test_server:start_node + (X, slave, [{args, "-pa " ++ PA}]), + J + end || X <- NN], + ?line NL1 = lists:duplicate(2,node()) ++ NL0, + ?line Perm = perm(NL1), + ?line lists:foreach( + fun(NL) -> + ?line Js = [ start_jeeves({[],M}) || M <- (NL ++ NL) ], + ?line [ask_jeeves(P,{monitor_process,self()}) || P <- Js], + ?line {monitored_by,MB} = + process_info(self(),monitored_by), + ?line MBL = lists:sort(MB), + ?line JsL = lists:sort(Js), + ?line MBL = JsL, + ?line {monitors,[]} = process_info(self(),monitors), + ?line [tell_jeeves(P,{exit,flaff}) || P <- Js], + ?line wait_for_m([],[],200) + end, + Perm), + ?line lists:foreach( + fun(NL) -> + ?line Js = [ start_jeeves({[],M}) || M <- (NL ++ NL) ], + ?line Rs = [begin + {monitor_process,Ref} = + ask_jeeves(P,{monitor_process,self()}), + {P,Ref} + end + || P <- Js], + ?line {monitored_by,MB} = + process_info(self(),monitored_by), + ?line MBL = lists:sort(MB), + ?line JsL = lists:sort(Js), + ?line MBL = JsL, + ?line {monitors,[]} = process_info(self(),monitors), + ?line [ask_jeeves(P,{demonitor,Ref}) || {P,Ref} <- Rs], + ?line wait_for_m([],[],200), + ?line [tell_jeeves(P,{exit,flaff}) || P <- Js] + end, + Perm), + ?line lists:foreach( + fun(NL) -> + ?line Js = [ start_jeeves({[],M}) || M <- (NL ++ NL) ], + ?line [ask_jeeves(P,{monitor_process,self()}) || P <- Js], + ?line [erlang:monitor(process,P) || P <- Js], + ?line {monitored_by,MB} = + process_info(self(),monitored_by), + ?line MBL = lists:sort(MB), + ?line JsL = lists:sort(Js), + ?line MBL = JsL, + ?line {monitors,M} = + process_info(self(),monitors), + ?line ML = lists:sort([P||{process,P} <- M]), + ?line ML = JsL, + ?line [begin + tell_jeeves(P,{exit,flaff}), + receive {'DOWN',_,process,P,_} -> ok end + end || P <- Js], + ?line wait_for_m([],[],200) + end, + Perm), + ?line lists:foreach( + fun(NL) -> + ?line Js = [ start_jeeves({[],M}) || M <- (NL ++ NL) ], + ?line Rs = [begin + {monitor_process,Ref} = + ask_jeeves(P,{monitor_process,self()}), + {P,Ref} + end + || P <- Js], + ?line R2s = [{P,erlang:monitor(process,P)} || P <- Js], + ?line {monitored_by,MB} = + process_info(self(),monitored_by), + ?line MBL = lists:sort(MB), + ?line JsL = lists:sort(Js), + ?line MBL = JsL, + ?line {monitors,M} = + process_info(self(),monitors), + ?line ML = lists:sort([P||{process,P} <- M]), + ?line ML = JsL, + ?line [ask_jeeves(P,{demonitor,Ref}) || {P,Ref} <- Rs], + ?line wait_for_m(lists:sort(M),[],200), + ?line [erlang:demonitor(Ref) || {_P,Ref} <- R2s], + ?line wait_for_m([],[],200), + ?line [tell_jeeves(P,{exit,flaff}) || P <- Js] + end, + Perm), + [test_server:stop_node(K) || K <- NL0 ], + ok. + +named_down(doc) -> ["Test that DOWN message for a named monitor isn't" + " delivered until name has been unregistered"]; +named_down(suite) -> []; +named_down(Config) when is_list(Config) -> + ?line {A,B,C} = now(), + ?line Name = list_to_atom(atom_to_list(?MODULE) + ++ "-named_down-" + ++ integer_to_list(A) + ++ "-" ++ integer_to_list(B) + ++ "-" ++ integer_to_list(C)), + ?line Prio = process_flag(priority,high), + %% Spawn a bunch of high prio cpu bound processes to prevent + %% normal prio processes from terminating during the next + %% 500 ms... + ?line Self = self(), + ?line spawn_opt(fun () -> + WFun = fun + (F, hej) -> F(F, hopp); + (F, hopp) -> F(F, hej) + end, + NoSchedulers = erlang:system_info(schedulers_online), + lists:foreach(fun (_) -> + spawn_opt(fun () -> + WFun(WFun, + hej) + end, + [{priority,high}, + link]) + end, + lists:seq(1, NoSchedulers)), + receive after 500 -> ok end, + unlink(Self), + exit(bang) + end, + [{priority,high}, link]), + ?line NamedProc = spawn_link(fun () -> + receive after infinity -> ok end + end), + ?line true = register(Name, NamedProc), + ?line unlink(NamedProc), + ?line exit(NamedProc, bang), + ?line Mon = erlang:monitor(process, Name), + ?line receive {'DOWN',Mon, _, _, _} -> ok end, + ?line true = register(Name, self()), + ?line true = unregister(Name), + ?line process_flag(priority,Prio), + ok. + +otp_5827(doc) -> []; +otp_5827(suite) -> []; +otp_5827(Config) when is_list(Config) -> + %% Make a pid with the same nodename but with another creation + ?line [CreEnd | RPTail] + = lists:reverse(binary_to_list(term_to_binary(self()))), + ?line NewCreEnd = case CreEnd of + 0 -> 1; + 1 -> 2; + _ -> CreEnd - 1 + end, + ?line OtherCreationPid + = binary_to_term(list_to_binary(lists:reverse([NewCreEnd | RPTail]))), + %% If the bug is present erlang:monitor(process, OtherCreationPid) + %% will hang... + ?line Parent = self(), + ?line Ok = make_ref(), + ?line spawn(fun () -> + Mon = erlang:monitor(process, OtherCreationPid), + % Should get the DOWN message right away + receive + {'DOWN', Mon, process, OtherCreationPid, noproc} -> + Parent ! Ok + end + end), + ?line receive + Ok -> + ?line ok + after 1000 -> + ?line ?t:fail("erlang:monitor/2 hangs") + end. + + +wait_for_m(_,_,0) -> + exit(monitor_wait_timeout); +wait_for_m(Monitors, MonitoredBy, N) -> + {monitors,M0} = process_info(self(),monitors), + {monitored_by,MB0} = process_info(self(),monitored_by), + case lists:sort(M0) of + Monitors -> + case lists:sort(MB0) of + MonitoredBy -> + ok; + _ -> + receive after 100 -> ok end, + wait_for_m(Monitors,MonitoredBy,N-1) + end; + _ -> + receive after 100 -> ok end, + wait_for_m(Monitors,MonitoredBy,N-1) + end. + +% All permutations of a list... +perm([]) -> + []; +perm([X]) -> + [[X]]; +perm(List) -> + perm([],List,[]). + +perm(_,[],Acc) -> + Acc; +perm(Pre,[El|Post],Acc) -> + Res = [[El|X] || X <- perm(Pre ++ Post)], + perm(Pre ++ [El], Post, Res ++ Acc). + + +%%% Our butler for named process monitor tests + +jeeves(Parent, Name, Ref) + when is_pid(Parent), (is_atom(Name) or (Name =:= [])), is_reference(Ref) -> + %%io:format("monitor_SUITE:jeeves(~p, ~p)~n", [Parent, Name]), + case Name of + Atom when is_atom(Atom) -> + register(Name, self()); + [] -> + ok + end, + Parent ! {self(), Ref}, + jeeves_loop(Parent). + +jeeves_loop(Parent) -> + receive + {Parent, monitors} -> + Parent ! {self(), {monitors, monitors()}}, + jeeves_loop(Parent); + {Parent, {monitor_process, P}} -> + Parent ! {self(), {monitor_process, + catch erlang:monitor(process, P) }}, + jeeves_loop(Parent); + {Parent, {demonitor, Ref}} -> + Parent ! {self(), {demonitor, catch erlang:demonitor(Ref)}}, + jeeves_loop(Parent); + {Parent, stop} -> + ok; + {Parent, {exit, Reason}} -> + exit(Reason); + Other -> + io:format("~p:jeeves_loop received ~p~n", [?MODULE, Other]) + end. + + +start_jeeves({Name, Node}) + when (is_atom(Name) or (Name =:= [])), is_atom(Node) -> + Parent = self(), + Ref = make_ref(), + Pid = spawn(Node, fun() -> jeeves(Parent, Name, Ref) end), + receive + {Pid, Ref} -> + ok; + Other -> + test_server:fail({rec, Other}) + end, + Pid; +start_jeeves(Name) when is_atom(Name) -> + start_jeeves({Name, node()}). + + +tell_jeeves(Pid, What) when is_pid(Pid) -> + Pid ! {self(), What}. + + +ask_jeeves(Pid, Request) when is_pid(Pid) -> + Pid ! {self(), Request}, + receive + {Pid, Response} -> + Response; + Other -> + test_server:fail({rec, Other}) + end. + + +expect_jeeves(Pid, Request, Response) when is_pid(Pid) -> + Pid ! {self(), Request}, + receive + {Pid, Response} -> + ok; + Other -> + test_server:fail({rec, Other}) + end. + + +monitors() -> + monitors(self()). + +monitors(Pid) when is_pid(Pid) -> + {monitors, Monitors} = process_info(self(), monitors), + {monitored_by, MonitoredBy} = process_info(self(), monitored_by), + {Monitors, MonitoredBy}. + +generate(_Fun, 0) -> + []; +generate(Fun, N) -> + [Fun() | generate(Fun, N-1)]. diff --git a/erts/emulator/test/nested_SUITE.erl b/erts/emulator/test/nested_SUITE.erl new file mode 100644 index 0000000000..310892424e --- /dev/null +++ b/erts/emulator/test/nested_SUITE.erl @@ -0,0 +1,92 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(nested_SUITE). + +-export([all/1, case_in_case/1, case_in_after/1, catch_in_catch/1, bif_in_bif/1]). + +-include("test_server.hrl"). + +all(suite) -> [case_in_case, case_in_after, catch_in_catch, bif_in_bif]. + +case_in_case(suite) -> []; +case_in_case(Config) when is_list(Config) -> + ?line done = search_any([a], [{a, 1}]), + ?line done = search_any([x], [{a, 1}]), + ok. + +search_any([Key|Rest], List) -> + ?line case case lists:keysearch(Key, 1, List) of + {value, _} -> + true; + _ -> + false + end of + true -> + ok; + false -> + error; + Other -> + test_server:fail({other_result, Other}) + end, + ?line search_any(Rest, List); +search_any([], _) -> + done. + +case_in_after(suite) -> []; +case_in_after(Config) when is_list(Config) -> + receive + after case {x, y, z} of + {x, y, z} -> 0 + end -> + ok + end, + ok. + +catch_in_catch(doc) -> "Test a catch within a catch in the same function."; +catch_in_catch(suite) -> []; +catch_in_catch(Config) when is_list(Config) -> + ?line {outer, inner_exit} = catcher(), + ok. + +catcher() -> + case (catch + case (catch ?MODULE:non_existing()) of % bogus function + {'EXIT', _} -> + inner_exit; + Res1 -> + {inner, Res1} + end) of + {'EXIT', _} -> + outer_exit; + Res2 -> + {outer, Res2} + end. + +bif_in_bif(doc) -> "Test a BIF call within a BIF call."; +bif_in_bif(suite) -> []; +bif_in_bif(Config) when is_list(Config) -> + Self = self(), + put(pid, Self), + Self = register_me(), + ok. + +register_me() -> + register(?MODULE, Pid = get(pid)), + Pid. diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl new file mode 100644 index 0000000000..213ff6637a --- /dev/null +++ b/erts/emulator/test/nif_SUITE.erl @@ -0,0 +1,235 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(nif_SUITE). + +%%-define(line_trace,true). + +-include("test_server.hrl"). + +-export([all/1, fin_per_testcase/2, basic/1, reload/1, upgrade/1, heap_frag/1, + neg/1]). + +-define(nif_stub,nif_stub_error(?LINE)). + +all(suite) -> + [basic, reload, upgrade, heap_frag, neg]. + +fin_per_testcase(_Func, _Config) -> + P1 = code:purge(nif_mod), + Del = code:delete(nif_mod), + P2 = code:purge(nif_mod), + io:format("fin purged=~p, deleted=~p and then purged=~p\n",[P1,Del,P2]). + +basic(doc) -> ["Basic smoke test of load_nif and a simple NIF call"]; +basic(suite) -> []; +basic(Config) when is_list(Config) -> + ensure_lib_loaded(Config), + ?line true = (lib_version() =/= undefined), + ?line [{load,1,1,101},{lib_version,1,2,102}] = call_history(), + ?line [] = call_history(), + ?line [?MODULE] = erlang:system_info(taints), + ok. + +reload(doc) -> ["Test reload callback in nif lib"]; +reload(suite) -> []; +reload(Config) when is_list(Config) -> + ensure_lib_loaded(Config), + + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "nif_mod"), + ?line {ok,nif_mod,Bin} = compile:file(File, [binary,return_errors]), + ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin), + + ?line nif_mod:load_nif_lib(Config, 1), + + ?line hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()), + ?line [{load,1,1,101},{get_priv_data_ptr,1,2,102}] = nif_mod_call_history(), + + ?line nif_mod:load_nif_lib(Config, 2), + ?line 2 = nif_mod:lib_version(), + ?line [{reload,2,1,201},{lib_version,2,2,202}] = nif_mod_call_history(), + + ?line nif_mod:load_nif_lib(Config, 1), + ?line 1 = nif_mod:lib_version(), + ?line [{reload,1,1,101},{lib_version,1,2,102}] = nif_mod_call_history(), + + ?line true = erlang:delete_module(nif_mod), + ?line [] = nif_mod_call_history(), + + %%?line false= check_process_code(Pid, nif_mod), + ?line true = erlang:purge_module(nif_mod), + ?line [{unload,1,3,103}] = nif_mod_call_history(), + + ?line [?MODULE, nif_mod] = erlang:system_info(taints), + ok. + +upgrade(doc) -> ["Test upgrade callback in nif lib"]; +upgrade(suite) -> []; +upgrade(Config) when is_list(Config) -> + ensure_lib_loaded(Config), + + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "nif_mod"), + ?line {ok,nif_mod,Bin} = compile:file(File, [binary,return_errors]), + ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin), + + ?line nif_mod:load_nif_lib(Config, 1), + ?line {Pid,MRef} = nif_mod:start(), + ?line 1 = call(Pid,lib_version), + + ?line hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()), + ?line [{load,1,1,101},{lib_version,1,2,102},{get_priv_data_ptr,1,3,103}] = nif_mod_call_history(), + + %% Module upgrade with same lib-version + ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin), + ?line undefined = nif_mod:lib_version(), + ?line 1 = call(Pid,lib_version), + ?line [{lib_version,1,4,104}] = nif_mod_call_history(), + + ?line nif_mod:load_nif_lib(Config, 1), + ?line 1 = nif_mod:lib_version(), + ?line [{upgrade,1,5,105},{lib_version,1,6,106}] = nif_mod_call_history(), + + ?line upgraded = call(Pid,upgrade), + ?line false = check_process_code(Pid, nif_mod), + ?line true = erlang:purge_module(nif_mod), + ?line [{unload,1,7,107}] = nif_mod_call_history(), + + ?line 1 = nif_mod:lib_version(), + ?line [{lib_version,1,8,108}] = nif_mod_call_history(), + + ?line true = erlang:delete_module(nif_mod), + ?line [] = nif_mod_call_history(), + + ?line Pid ! die, + ?line {'DOWN', MRef, process, Pid, normal} = receive_any(), + ?line false = check_process_code(Pid, nif_mod), + ?line true = erlang:purge_module(nif_mod), + ?line [{unload,1,9,109}] = nif_mod_call_history(), + + %% Module upgrade with different lib version + ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin), + ?line undefined = nif_mod:lib_version(), + ?line {Pid2,MRef2} = nif_mod:start(), + ?line undefined = call(Pid2,lib_version), + + ?line nif_mod:load_nif_lib(Config, 1), + ?line hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()), + ?line 1 = call(Pid2,lib_version), + ?line [{load,1,1,101},{get_priv_data_ptr,1,2,102},{lib_version,1,3,103}] = nif_mod_call_history(), + + ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin), + ?line undefined = nif_mod:lib_version(), + ?line [] = nif_mod_call_history(), + ?line 1 = call(Pid2,lib_version), + ?line [{lib_version,1,4,104}] = nif_mod_call_history(), + + ?line nif_mod:load_nif_lib(Config, 2), + ?line 2 = nif_mod:lib_version(), + ?line [{upgrade,2,1,201},{lib_version,2,2,202}] = nif_mod_call_history(), + + ?line 1 = call(Pid2,lib_version), + ?line [{lib_version,1,5,105}] = nif_mod_call_history(), + + ?line upgraded = call(Pid2,upgrade), + ?line false = check_process_code(Pid2, nif_mod), + ?line true = erlang:purge_module(nif_mod), + ?line [{unload,1,6,106}] = nif_mod_call_history(), + + ?line 2 = nif_mod:lib_version(), + ?line [{lib_version,2,3,203}] = nif_mod_call_history(), + + ?line true = erlang:delete_module(nif_mod), + ?line [] = nif_mod_call_history(), + + ?line Pid2 ! die, + ?line {'DOWN', MRef2, process, Pid2, normal} = receive_any(), + ?line false= check_process_code(Pid2, nif_mod), + ?line true = erlang:purge_module(nif_mod), + ?line [{unload,2,4,204}] = nif_mod_call_history(), + + ?line [?MODULE, nif_mod] = erlang:system_info(taints), + ok. + +heap_frag(doc) -> ["Test NIF building heap fragments"]; +heap_frag(suite) -> []; +heap_frag(Config) when is_list(Config) -> + ensure_lib_loaded(Config), + + heap_frag_do(1,1000000), + ok. + +heap_frag_do(N, Max) when N > Max -> + ok; +heap_frag_do(N, Max) -> + io:format("Create list of length ~p\n",[N]), + L = lists:seq(1,N), + L = list_seq(N), + heap_frag_do(((N*5) div 4) + 1, Max). + + +neg(doc) -> ["Negative testing of load_nif"]; +neg(suite) -> []; +neg(Config) when is_list(Config) -> + ?line {'EXIT',{badarg,_}} = (catch erlang:load_nif(badarg, 0)), + ?line {error,load_failed,_} = erlang:load_nif("pink_unicorn", 0), + + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "nif_mod"), + ?line {ok,nif_mod,Bin} = compile:file(File, [binary,return_errors]), + ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin), + + ?line {error,bad_lib,_} = nif_mod:load_nif_lib(Config, no_init), + ?line ok. + + + +ensure_lib_loaded(Config) -> + ensure_lib_loaded(Config, 1). + +ensure_lib_loaded(Config, Ver) -> + ?line case lib_version() of + undefined -> + ?line Path = ?config(data_dir, Config), + ?line Lib = "nif_SUITE." ++ integer_to_list(Ver), + ?line ok = erlang:load_nif(filename:join(Path,Lib), 0); + Ver when is_integer(Ver) -> + ok + end. + +call(Pid,Cmd) -> + %%io:format("~p calling ~p with ~p\n",[self(), Pid, Cmd]), + Pid ! {self(), Cmd}, + receive + {Pid,Reply} -> Reply + end. + +receive_any() -> + receive M -> M end. + +%% The NIFs: +lib_version() -> undefined. +call_history() -> ?nif_stub. +hold_nif_mod_priv_data(_Ptr) -> ?nif_stub. +nif_mod_call_history() -> ?nif_stub. +list_seq(_To) -> ?nif_stub. + +nif_stub_error(Line) -> + exit({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/erts/emulator/test/nif_SUITE_data/Makefile.src b/erts/emulator/test/nif_SUITE_data/Makefile.src new file mode 100644 index 0000000000..6a8b4f1245 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/Makefile.src @@ -0,0 +1,14 @@ + +NIF_LIBS = nif_SUITE.1@dll@ \ + nif_mod.1@dll@ \ + nif_mod.2@dll@ \ + nif_mod.3@dll@ + +all: $(NIF_LIBS) + + +@SHLIB_RULES@ + +$(NIF_LIBS): nif_SUITE.c nif_mod.c nif_mod.h + + diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.1.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.1.c new file mode 100644 index 0000000000..71626043dd --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.1.c @@ -0,0 +1,2 @@ +#define NIF_SUITE_LIB_VER 1 +#include "nif_SUITE.c" diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c new file mode 100644 index 0000000000..852495e234 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -0,0 +1,149 @@ +#include "erl_nif.h" +#include <string.h> +#include <assert.h> + +#include "nif_mod.h" + +static int static_cntA; /* zero by default */ +static int static_cntB = NIF_SUITE_LIB_VER * 100; + +typedef struct +{ + int ref_cnt; + CallInfo* call_history; + NifModPrivData* nif_mod; +}PrivData; + +void add_call(ErlNifEnv* env, PrivData* data, const char* func_name) +{ + CallInfo* call = enif_alloc(env, sizeof(CallInfo)+strlen(func_name)); + strcpy(call->func_name, func_name); + call->lib_ver = NIF_SUITE_LIB_VER; + call->next = data->call_history; + call->static_cntA = ++static_cntA; + call->static_cntB = ++static_cntB; + data->call_history = call; +} + +#define ADD_CALL(FUNC_NAME) add_call(env, enif_get_data(env),FUNC_NAME) + +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + PrivData* data = enif_alloc(env, sizeof(PrivData)); + assert(data != NULL); + data->ref_cnt = 1; + data->call_history = NULL; + data->nif_mod = NULL; + + add_call(env, data, "load"); + + *priv_data = data; + return 0; +} + +static int reload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + add_call(env, *priv_data, "reload"); + return 0; +} + +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info) +{ + PrivData* data = *old_priv_data; + add_call(env, data, "upgrade"); + data->ref_cnt++; + *priv_data = *old_priv_data; + return 0; +} + +static void unload(ErlNifEnv* env, void* priv_data) +{ + PrivData* data = priv_data; + add_call(env, data, "unload"); + if (--data->ref_cnt == 0) { + enif_free(env, priv_data); + } +} + +static ERL_NIF_TERM lib_version(ErlNifEnv* env) +{ + ADD_CALL("lib_version"); + return enif_make_int(env, NIF_SUITE_LIB_VER); +} + +static ERL_NIF_TERM make_call_history(ErlNifEnv* env, CallInfo** headp) +{ + ERL_NIF_TERM list = enif_make_list(env, 0); /* NIL */ + + while (*headp != NULL) { + CallInfo* call = *headp; + ERL_NIF_TERM tpl = enif_make_tuple(env, 4, + enif_make_atom(env,call->func_name), + enif_make_int(env,call->lib_ver), + enif_make_int(env,call->static_cntA), + enif_make_int(env,call->static_cntB)); + list = enif_make_list_cell(env, tpl, list); + *headp = call->next; + enif_free(env,call); + } + return list; +} + +static ERL_NIF_TERM call_history(ErlNifEnv* env) +{ + PrivData* data = (PrivData*) enif_get_data(env); + + return make_call_history(env,&data->call_history); +} + +static ERL_NIF_TERM hold_nif_mod_priv_data(ErlNifEnv* env, ERL_NIF_TERM a1) +{ + PrivData* data = (PrivData*) enif_get_data(env); + unsigned long ptr_as_ulong; + + if (!enif_get_ulong(env,a1,&ptr_as_ulong)) { + return enif_make_badarg(env); + } + if (data->nif_mod != NULL && --(data->nif_mod->ref_cnt) == 0) { + enif_free(env,data->nif_mod); + } + data->nif_mod = (NifModPrivData*) ptr_as_ulong; + return enif_make_int(env,++(data->nif_mod->ref_cnt)); +} + +static ERL_NIF_TERM nif_mod_call_history(ErlNifEnv* env) +{ + PrivData* data = (PrivData*) enif_get_data(env); + + if (data->nif_mod == NULL) { + return enif_make_string(env,"nif_mod pointer is NULL"); + } + return make_call_history(env,&data->nif_mod->call_history); +} + +static ERL_NIF_TERM list_seq(ErlNifEnv* env, ERL_NIF_TERM a1) +{ + ERL_NIF_TERM list; + int n; + if (!enif_get_int(env, a1, &n)) { + return enif_make_badarg(env); + } + list = enif_make_list(env, 0); /* NIL */ + while (n > 0) { + list = enif_make_list_cell(env, enif_make_int(env,n), list); + n--; + } + return list; +} + +static ErlNifFunc nif_funcs[] = +{ + {"lib_version", 0, lib_version}, + {"call_history", 0, call_history}, + {"hold_nif_mod_priv_data", 1, hold_nif_mod_priv_data}, + {"nif_mod_call_history", 0, nif_mod_call_history}, + {"list_seq", 1, list_seq} +}; + +ERL_NIF_INIT(nif_SUITE,nif_funcs,load,reload,upgrade,unload) + diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.1.c b/erts/emulator/test/nif_SUITE_data/nif_mod.1.c new file mode 100644 index 0000000000..5e508570bd --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.1.c @@ -0,0 +1,2 @@ +#define NIF_LIB_VER 1 +#include "nif_mod.c" diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.2.c b/erts/emulator/test/nif_SUITE_data/nif_mod.2.c new file mode 100644 index 0000000000..5dd5d88766 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.2.c @@ -0,0 +1,2 @@ +#define NIF_LIB_VER 2 +#include "nif_mod.c" diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.3.c b/erts/emulator/test/nif_SUITE_data/nif_mod.3.c new file mode 100644 index 0000000000..8cbcb748a3 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.3.c @@ -0,0 +1,2 @@ +#define NIF_LIB_VER 3 +#include "nif_mod.c" diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.c b/erts/emulator/test/nif_SUITE_data/nif_mod.c new file mode 100644 index 0000000000..18f676335a --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.c @@ -0,0 +1,103 @@ +#include "erl_nif.h" +#include <string.h> +#include <assert.h> + +#include "nif_mod.h" + + +static int static_cntA; /* zero by default */ +static int static_cntB = NIF_LIB_VER * 100; + +static void add_call(ErlNifEnv* env, NifModPrivData* data, const char* func_name) +{ + CallInfo* call = enif_alloc(env, sizeof(CallInfo)+strlen(func_name)); + strcpy(call->func_name, func_name); + call->lib_ver = NIF_LIB_VER; + call->static_cntA = ++static_cntA; + call->static_cntB = ++static_cntB; + call->next = data->call_history; + data->call_history = call; +} + +#define ADD_CALL(FUNC_NAME) add_call(env, enif_get_data(env),FUNC_NAME) + +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + NifModPrivData* data = enif_alloc(env, sizeof(NifModPrivData)); + assert(data != NULL); + data->ref_cnt = 1; + data->call_history = NULL; + add_call(env, data, "load"); + + data->calls = 0; + *priv_data = data; + return 0; +} + +static int reload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + add_call(env, *priv_data, "reload"); + return 0; +} + +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info) +{ + NifModPrivData* data = *old_priv_data; + add_call(env, data, "upgrade"); + data->ref_cnt++; + *priv_data = *old_priv_data; + return 0; +} + +static void unload(ErlNifEnv* env, void* priv_data) +{ + NifModPrivData* data = priv_data; + add_call(env, data, "unload"); + if (--data->ref_cnt == 0) { + enif_free(env, data); + } +} + +static ERL_NIF_TERM lib_version(ErlNifEnv* env) +{ + ADD_CALL("lib_version"); + return enif_make_int(env, NIF_LIB_VER); +} + +static ERL_NIF_TERM call_history(ErlNifEnv* env) +{ + NifModPrivData* data = (NifModPrivData*) enif_get_data(env); + ERL_NIF_TERM list = enif_make_list(env, 0); /* NIL */ + + while (data->call_history != NULL) { + CallInfo* call = data->call_history; + ERL_NIF_TERM tpl = enif_make_tuple(env, 2, + enif_make_atom(env,call->func_name), + enif_make_int(env,call->lib_ver)); + list = enif_make_list_cell(env, tpl, list); + data->call_history = call->next; + enif_free(env,call); + } + return list; +} + +static ERL_NIF_TERM get_priv_data_ptr(ErlNifEnv* env) +{ + ADD_CALL("get_priv_data_ptr"); + return enif_make_ulong(env, (unsigned long)enif_get_data(env)); +} + + +static ErlNifFunc nif_funcs[] = +{ + {"lib_version", 0, lib_version}, + {"call_history", 0, call_history}, + {"get_priv_data_ptr", 0, get_priv_data_ptr} +}; + +#if NIF_LIB_VER != 3 +ERL_NIF_INIT(nif_mod,nif_funcs,load,reload,upgrade,unload) +#else +ERL_NIF_INIT_GLOB /* avoid link error on windows */ +#endif + diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.erl b/erts/emulator/test/nif_SUITE_data/nif_mod.erl new file mode 100644 index 0000000000..93da6590a0 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.erl @@ -0,0 +1,64 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(nif_mod). + +-include("test_server.hrl"). + +-export([load_nif_lib/2, start/0, lib_version/0, call_history/0, get_priv_data_ptr/0]). + +-export([loop/0, upgrade/1]). + +-define(nif_stub,nif_stub_error(?LINE)). + +load_nif_lib(Config, Ver) -> + ?line Path = ?config(data_dir, Config), + erlang:load_nif(filename:join(Path,libname(Ver)), 0). + +libname(no_init) -> libname(3); +libname(Ver) when is_integer(Ver) -> + "nif_mod." ++ integer_to_list(Ver). + +start() -> + spawn_opt(?MODULE,loop,[], + [link, monitor]). + +loop() -> + receive + {Pid,lib_version} -> + Pid ! {self(),lib_version()}, + loop(); + {Pid,upgrade} -> + ?MODULE:upgrade(Pid); + die -> + void + end. + +upgrade(Pid) -> + Pid ! {self(),upgraded}, + loop(). + +lib_version() -> % NIF + undefined. + +call_history() -> ?nif_stub. +get_priv_data_ptr() -> ?nif_stub. + +nif_stub_error(Line) -> + exit({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.h b/erts/emulator/test/nif_SUITE_data/nif_mod.h new file mode 100644 index 0000000000..2dfdc75176 --- /dev/null +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.h @@ -0,0 +1,17 @@ +typedef struct call_info_t +{ + struct call_info_t* next; + unsigned lib_ver; + int static_cntA; + int static_cntB; + char func_name[1]; /* must be last */ +}CallInfo; + + +typedef struct +{ + int calls; + int ref_cnt; + CallInfo* call_history; +}NifModPrivData; + diff --git a/erts/emulator/test/node_container_SUITE.erl b/erts/emulator/test/node_container_SUITE.erl new file mode 100644 index 0000000000..f3d9eb783b --- /dev/null +++ b/erts/emulator/test/node_container_SUITE.erl @@ -0,0 +1,1288 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%%---------------------------------------------------------------------- +%%% File : node_container_SUITE.erl +%%% Author : Rickard <[email protected]> +%%% Purpose : +%%% Created : 24 Jul 2002 by Rickard <[email protected]> +%%%---------------------------------------------------------------------- + +-module(node_container_SUITE). +-author('[email protected]'). + +%-define(line_trace, 1). + +-include("test_server.hrl"). + +%-compile(export_all). +-export([all/1, init_per_testcase/2, fin_per_testcase/2, end_per_suite/1, + node_container_refc_check/1]). + +-export([term_to_binary_to_term_eq/1, + round_trip_eq/1, + cmp/1, + ref_eq/1, + node_table_gc/1, + dist_link_refc/1, + dist_monitor_refc/1, + node_controller_refc/1, + ets_refc/1, + match_spec_refc/1, + timer_refc/1, + otp_4715/1, + pid_wrap/1, + port_wrap/1, + bad_nc/1, + unique_pid/1, + iter_max_procs/1]). + +-define(DEFAULT_TIMEOUT, ?t:minutes(10)). + +all(doc) -> []; +all(suite) -> + [term_to_binary_to_term_eq, + round_trip_eq, + cmp, + ref_eq, + node_table_gc, + dist_link_refc, + dist_monitor_refc, + node_controller_refc, + ets_refc, + match_spec_refc, + timer_refc, + otp_4715, + pid_wrap, + port_wrap, + bad_nc, + unique_pid, + iter_max_procs]. + +available_internal_state(Bool) when Bool == true; Bool == false -> + case {Bool, + (catch erts_debug:get_internal_state(available_internal_state))} of + {true, true} -> + true; + {false, true} -> + erts_debug:set_internal_state(available_internal_state, false), + true; + {true, _} -> + erts_debug:set_internal_state(available_internal_state, true), + false; + {false, _} -> + false + end. + +init_per_testcase(_Case, Config) when is_list(Config) -> + Dog = ?t:timetrap(?DEFAULT_TIMEOUT), + available_internal_state(true), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +end_per_suite(_Config) -> + available_internal_state(false). + +%%% +%%% The test cases ------------------------------------------------------------- +%%% + +-define(MAX_PIDS_PORTS, ((1 bsl 28) - 1)). + +%% +%% Test case: term_to_binary_to_term_eq +%% +term_to_binary_to_term_eq(doc) -> + ["Tests that node container terms that are converted to external format " + "and back stay equal to themselves."]; +term_to_binary_to_term_eq(suite) -> []; +term_to_binary_to_term_eq(Config) when is_list(Config) -> + ?line ThisNode = {node(), erlang:system_info(creation)}, + % Get local node containers + ?line LPid = self(), + ?line LXPid = mk_pid(ThisNode, 32767, 8191), + ?line LPort = hd(erlang:ports()), + ?line LXPort = mk_port(ThisNode, 268435455), + ?line LLRef = make_ref(), + ?line LHLRef = mk_ref(ThisNode, [47, 11]), + ?line LSRef = mk_ref(ThisNode, [4711]), + % Test local nc:s + ?line LPid = binary_to_term(term_to_binary(LPid)), + ?line LXPid = binary_to_term(term_to_binary(LXPid)), + ?line LPort = binary_to_term(term_to_binary(LPort)), + ?line LXPort = binary_to_term(term_to_binary(LXPort)), + ?line LLRef = binary_to_term(term_to_binary(LLRef)), + ?line LHLRef = binary_to_term(term_to_binary(LHLRef)), + ?line LSRef = binary_to_term(term_to_binary(LSRef)), + % Get remote node containers + ?line RNode = {get_nodename(), 3}, + ?line RPid = mk_pid(RNode, 4711, 1), + ?line RXPid = mk_pid(RNode, 32767, 8191), + ?line RPort = mk_port(RNode, 4711), + ?line RXPort = mk_port(RNode, 268435455), + ?line RLRef = mk_ref(RNode, [4711, 4711, 4711]), + ?line RHLRef = mk_ref(RNode, [4711, 4711]), + ?line RSRef = mk_ref(RNode, [4711]), + % Test remote nc:s + ?line RPid = binary_to_term(term_to_binary(RPid)), + ?line RXPid = binary_to_term(term_to_binary(RXPid)), + ?line RPort = binary_to_term(term_to_binary(RPort)), + ?line RXPort = binary_to_term(term_to_binary(RXPort)), + ?line RLRef = binary_to_term(term_to_binary(RLRef)), + ?line RHLRef = binary_to_term(term_to_binary(RHLRef)), + ?line RSRef = binary_to_term(term_to_binary(RSRef)), + ?line nc_refc_check(node()), + ?line ok. + + +%% +%% Test case: round_trip_eq +%% +round_trip_eq(doc) -> + ["Tests that node containers that are sent beteen nodes stay equal to " + "themselves."]; +round_trip_eq(suite) -> []; +round_trip_eq(Config) when is_list(Config) -> + ?line ThisNode = {node(), erlang:system_info(creation)}, + ?line NodeFirstName = get_nodefirstname(), + ?line ?line {ok, Node} = start_node(NodeFirstName), + ?line Self = self(), + ?line RPid = spawn_link(Node, + fun () -> + receive + {Self, Data} -> + Self ! {self(), Data} + end + end), + ?line SentPid = self(), + ?line SentXPid = mk_pid(ThisNode, 17471, 8190), + ?line SentPort = hd(erlang:ports()), + ?line SentXPort = mk_port(ThisNode, 268435451), + ?line SentLRef = make_ref(), + ?line SentHLRef = mk_ref(ThisNode, [4711, 17]), + ?line SentSRef = mk_ref(ThisNode, [4711]), + ?line RPid ! {Self, {SentPid, + SentXPid, + SentPort, + SentXPort, + SentLRef, + SentHLRef, + SentSRef}}, + receive + {RPid, {RecPid, + RecXPid, + RecPort, + RecXPort, + RecLRef, + RecHLRef, + RecSRef}} -> + ?line stop_node(Node), + ?line SentPid = RecPid, + ?line SentXPid = RecXPid, + ?line SentPort = RecPort, + ?line SentXPort = RecXPort, + ?line SentLRef = RecLRef, + ?line SentHLRef = RecHLRef, + ?line SentSRef = RecSRef, + ?line nc_refc_check(node()), + ?line ok + end. + + + +%% +%% Test case: cmp +%% +cmp(doc) -> + ["Tests that Erlang term comparison works as it should on node " + "containers."]; +cmp(suite) -> []; +cmp(Config) when is_list(Config) -> + + %% Inter type comparison --------------------------------------------------- + + %% The Erlang term order: + %% number < atom < ref < fun < port < pid < tuple < nil < cons < binary + RNode = {get_nodename(), 2}, + + IRef = make_ref(), + ERef = mk_ref({get_nodename(), 2}, [1,2,3]), + + IPid = self(), + EPid = mk_pid(RNode, 1, 2), + + IPort = hd(erlang:ports()), + EPort = mk_port(RNode, 1), + + %% Test pids ---------------------------------------------------- + ?line true = 1 < IPid, + ?line true = 1.3 < IPid, + ?line true = (1 bsl 64) < IPid, + ?line true = an_atom < IPid, + ?line true = IRef < IPid, + ?line true = ERef < IPid, + ?line true = fun () -> a_fun end < IPid, + ?line true = IPort < IPid, + ?line true = EPort < IPid, + ?line true = IPid < {a, tuple}, + ?line true = IPid < [], + ?line true = IPid < [a|cons], + ?line true = IPid < <<"a binary">>, + + ?line true = 1 < EPid, + ?line true = 1.3 < EPid, + ?line true = (1 bsl 64) < EPid, + ?line true = an_atom < EPid, + ?line true = IRef < EPid, + ?line true = ERef < EPid, + ?line true = fun () -> a_fun end < EPid, + ?line true = IPort < EPid, + ?line true = EPort < EPid, + ?line true = EPid < {a, tuple}, + ?line true = EPid < [], + ?line true = EPid < [a|cons], + ?line true = EPid < <<"a binary">>, + + %% Test ports -------------------------------------------------- + ?line true = 1 < IPort, + ?line true = 1.3 < IPort, + ?line true = (1 bsl 64) < IPort, + ?line true = an_atom < IPort, + ?line true = IRef < IPort, + ?line true = ERef < IPort, + ?line true = fun () -> a_fun end < IPort, + ?line true = IPort < IPid, + ?line true = IPort < EPid, + ?line true = IPort < {a, tuple}, + ?line true = IPort < [], + ?line true = IPort < [a|cons], + ?line true = IPort < <<"a binary">>, + + ?line true = 1 < EPort, + ?line true = 1.3 < EPort, + ?line true = (1 bsl 64) < EPort, + ?line true = an_atom < EPort, + ?line true = IRef < EPort, + ?line true = ERef < EPort, + ?line true = fun () -> a_fun end < EPort, + ?line true = EPort < IPid, + ?line true = EPort < EPid, + ?line true = EPort < {a, tuple}, + ?line true = EPort < [], + ?line true = EPort < [a|cons], + ?line true = EPort < <<"a binary">>, + + %% Test refs ---------------------------------------------------- + ?line true = 1 < IRef, + ?line true = 1.3 < IRef, + ?line true = (1 bsl 64) < IRef, + ?line true = an_atom < IRef, + ?line true = IRef < fun () -> a_fun end, + ?line true = IRef < IPort, + ?line true = IRef < EPort, + ?line true = IRef < IPid, + ?line true = IRef < EPid, + ?line true = IRef < {a, tuple}, + ?line true = IRef < [], + ?line true = IRef < [a|cons], + ?line true = IRef < <<"a binary">>, + + ?line true = 1 < ERef, + ?line true = 1.3 < ERef, + ?line true = (1 bsl 64) < ERef, + ?line true = an_atom < ERef, + ?line true = ERef < fun () -> a_fun end, + ?line true = ERef < IPort, + ?line true = ERef < EPort, + ?line true = ERef < IPid, + ?line true = ERef < EPid, + ?line true = ERef < {a, tuple}, + ?line true = ERef < [], + ?line true = ERef < [a|cons], + ?line true = ERef < <<"a binary">>, + + + %% Intra type comparison --------------------------------------------------- + + + %% Test pids ---------------------------------------------------- + %% + %% Significance (most -> least): + %% serial, number, nodename, creation + %% + + ?line Pid = mk_pid({b@b, 2}, 4711, 1), + + ?line true = mk_pid({a@b, 1}, 4710, 2) > Pid, + ?line true = mk_pid({a@b, 1}, 4712, 1) > Pid, + ?line true = mk_pid({c@b, 1}, 4711, 1) > Pid, + ?line true = mk_pid({b@b, 3}, 4711, 1) > Pid, + ?line true = mk_pid({b@b, 2}, 4711, 1) =:= Pid, + + %% Test ports --------------------------------------------------- + %% + %% Significance (most -> least): + %% nodename, creation, number + %% + %% OBS: Comparison between ports has changed in R9. This + %% since it wasn't stable in R8 (and eariler releases). + %% Significance used to be: dist_slot, number, + %% creation. + + ?line Port = mk_port({b@b, 2}, 4711), + + ?line true = mk_port({c@b, 1}, 4710) > Port, + ?line true = mk_port({b@b, 3}, 4710) > Port, + ?line true = mk_port({b@b, 2}, 4712) > Port, + ?line true = mk_port({b@b, 2}, 4711) =:= Port, + + %% Test refs ---------------------------------------------------- + %% Significance (most -> least): + %% nodename, creation, (number high, number mid), number low, + %% + %% OBS: Comparison between refs has changed in R9. This + %% since it wasn't stable in R8 (and eariler releases). + %% Significance used to be: dist_slot, number, + %% creation. + %% + + ?line Ref = mk_ref({b@b, 2}, [4711, 4711, 4711]), + + ?line true = mk_ref({c@b, 1}, [4710, 4710, 4710]) > Ref, + ?line true = mk_ref({b@b, 3}, [4710, 4710, 4710]) > Ref, + ?line true = mk_ref({b@b, 2}, [4710, 4710, 4712]) > Ref, + ?line true = mk_ref({b@b, 2}, [4710, 4712, 4711]) > Ref, + ?line true = mk_ref({b@b, 2}, [4712, 4711, 4711]) > Ref, + ?line true = mk_ref({b@b, 2}, [4711, 4711, 4711]) =:= Ref, + + ok. + +%% +%% Test case: ref_eq +%% +ref_eq(doc) -> ["Test that one word refs \"works\"."]; +ref_eq(suite) -> []; +ref_eq(Config) when is_list(Config) -> + ?line ThisNode = {node(), erlang:system_info(creation)}, + ?line AnotherNode = {get_nodename(),2}, + ?line LLongRef = mk_ref(ThisNode, [4711, 0, 0]), + ?line LHalfLongRef = mk_ref(ThisNode, [4711, 0]), + ?line LShortRef = mk_ref(ThisNode, [4711]), + ?line true = LLongRef =:= LShortRef, + ?line true = LLongRef =:= LHalfLongRef, + ?line true = LLongRef =:= LLongRef, + ?line true = LHalfLongRef =:= LShortRef, + ?line true = LHalfLongRef =:= LHalfLongRef, + ?line true = LShortRef =:= LShortRef, + ?line false = LShortRef == mk_ref(ThisNode, [4711, 0, 1]), % Not any more + ?line RLongRef = mk_ref(AnotherNode, [4711, 0, 0]), + ?line RHalfLongRef = mk_ref(AnotherNode, [4711, 0]), + ?line RShortRef = mk_ref(AnotherNode, [4711]), + ?line true = RLongRef =:= RShortRef, + ?line true = RLongRef =:= RHalfLongRef, + ?line true = RLongRef =:= RLongRef, + ?line true = RHalfLongRef =:= RShortRef, + ?line true = RHalfLongRef =:= RHalfLongRef, + ?line true = RShortRef =:= RShortRef, + ?line false = RShortRef == mk_ref(AnotherNode, [4711, 0, 1]), % Not any more + ?line nc_refc_check(node()), + ?line ok. + +%% +%% Test case: node_table_gc +%% +node_table_gc(doc) -> + ["Tests that node tables are garbage collected."]; +node_table_gc(suite) -> []; +node_table_gc(Config) when is_list(Config) -> + ?line PreKnown = nodes(known), + ?line ?t:format("PreKnown = ~p~n", [PreKnown]), + ?line make_node_garbage(0, 200000, 1000, []), + ?line PostKnown = nodes(known), + ?line PostAreas = erlang:system_info(allocated_areas), + ?line ?t:format("PostKnown = ~p~n", [PostKnown]), + ?line ?t:format("PostAreas = ~p~n", [PostAreas]), + ?line true = length(PostKnown) =< length(PreKnown), + ?line nc_refc_check(node()), + ?line ok. + +make_node_garbage(N, L, I, Ps) when N < L -> + ?line Self = self(), + ?line P = spawn_link(fun () -> + % Generate two node entries and one dist + % entry per node name + ?line PL1 = make_faked_pid_list(N, + I div 2, + 1), + ?line put(a, PL1), + ?line PL2 = make_faked_pid_list(N, + I div 2, + 2), + ?line put(b, PL2), + ?line Self ! {self(), length(nodes(known))} + end), + ?line receive + {P, KnownLength} -> + ?line true = KnownLength >= I div 2 + end, + ?line make_node_garbage(N+(I div 2)*2, L, I, [P|Ps]); +make_node_garbage(_, _, _, Ps) -> + %% Cleanup garbage... + ProcIsCleanedUp + = fun (Proc) -> + undefined == erts_debug:get_internal_state({process_status, + Proc}) + end, + lists:foreach(fun (P) -> wait_until(fun () -> ProcIsCleanedUp(P) end) end, + Ps), + ?line case erlang:system_info(heap_type) of + shared -> ?line garbage_collect(); + _ -> ?line ok + end, + ?line ok. + + +make_faked_pid_list(Start, No, Creation) -> + make_faked_pid_list(Start, No, Creation, []). + +make_faked_pid_list(_Start, 0, _Creation, Acc) -> + Acc; +make_faked_pid_list(Start, No, Creation, Acc) -> + make_faked_pid_list(Start+1, + No-1, + Creation, + [mk_pid({"faked_node-" + ++ integer_to_list(Start rem 50000) + ++ "@" + ++ atom_to_list(?MODULE), + Creation}, + 4711, + 3) | Acc]). + +%% +%% Test case: dist_link_refc +%% +dist_link_refc(doc) -> + ["Tests that external reference counts are incremented and decremented " + "as they should for distributed links"]; +dist_link_refc(suite) -> []; +dist_link_refc(Config) when is_list(Config) -> + ?line NodeFirstName = get_nodefirstname(), + ?line ?line {ok, Node} = start_node(NodeFirstName), + ?line RP = spawn_execer(Node), + ?line LP = spawn_link_execer(node()), + ?line true = sync_exec(RP, fun () -> link(LP) end), + ?line wait_until(fun () -> + ?line {links, Links} = process_info(LP, links), + ?line lists:member(RP, Links) + end), + ?line NodeCre = sync_exec(RP, fun() -> erlang:system_info(creation) end), + ?line 1 = reference_type_count( + link, + refering_entity_id({process, LP}, + get_node_references({Node, NodeCre}))), + ?line exec(RP, fun() -> exit(normal) end), + ?line wait_until(fun () -> + ?line {links, Links} = process_info(LP, links), + ?line not lists:member(RP, Links) + end), + ?line 0 = reference_type_count( + link, + refering_entity_id({process, LP}, + get_node_references({Node, NodeCre}))), + ?line exit(LP, normal), + ?line stop_node(Node), + ?line nc_refc_check(node()), + ?line ok. + + +%% +%% Test case: dist_monitor_refc +%% +dist_monitor_refc(doc) -> + ["Tests that external reference counts are incremented and decremented " + "as they should for distributed monitors"]; +dist_monitor_refc(suite) -> []; +dist_monitor_refc(Config) when is_list(Config) -> + ?line NodeFirstName = get_nodefirstname(), + ?line {ok, Node} = start_node(NodeFirstName), + ?line RP = spawn_execer(Node), + ?line LP = spawn_link_execer(node()), + ?line RMon = sync_exec(RP, fun () -> erlang:monitor(process, LP) end), + ?line true = is_reference(RMon), + ?line LMon = sync_exec(LP, fun () -> erlang:monitor(process, RP) end), + ?line true = is_reference(LMon), + ?line NodeCre = sync_exec(RP, fun() -> erlang:system_info(creation) end), + ?line wait_until(fun () -> + ?line {monitored_by, MonBy} + = process_info(LP, monitored_by), + ?line {monitors, Mon} + = process_info(LP, monitors), + ?line (lists:member(RP, MonBy) + and lists:member({process,RP}, Mon)) + end), + ?line 3 = reference_type_count( + monitor, + refering_entity_id({process, LP}, + get_node_references({Node, NodeCre}))), + ?line exec(RP, fun () -> exit(normal) end), + ?line wait_until(fun () -> + ?line {monitored_by, MonBy} + = process_info(LP, monitored_by), + ?line {monitors, Mon} + = process_info(LP, monitors), + ?line ((not lists:member(RP, MonBy)) + and (not lists:member({process,RP}, Mon))) + end), + ?line ok = sync_exec(LP, + fun () -> + receive + {'DOWN', LMon, process, _, _} -> + ok + end + end), + ?line 0 = reference_type_count( + link, + refering_entity_id({process, LP}, + get_node_references({Node, NodeCre}))), + ?line exit(LP, normal), + ?line stop_node(Node), + ?line nc_refc_check(node()), + ?line ok. + + +%% +%% Test case: node_controller_refc +%% +node_controller_refc(doc) -> + ["Tests that external reference counts are incremented and decremented " + "as they should for entities controlling a connections."]; +node_controller_refc(suite) -> []; +node_controller_refc(Config) when is_list(Config) -> + ?line NodeFirstName = get_nodefirstname(), + ?line ?line {ok, Node} = start_node(NodeFirstName), + ?line true = lists:member(Node, nodes()), + ?line 1 = reference_type_count(control, get_dist_references(Node)), + ?line P = spawn_link_execer(node()), + ?line Node + = sync_exec(P, + fun () -> + put(remote_net_kernel, + rpc:call(Node,erlang,whereis,[net_kernel])), + node(get(remote_net_kernel)) + end), + ?line Creation = rpc:call(Node, erlang, system_info, [creation]), + ?line monitor_node(Node,true), + ?line stop_node(Node), + ?line receive {nodedown, Node} -> ok end, + ?line DistRefs = get_dist_references(Node), + ?line true = reference_type_count(node, DistRefs) > 0, + ?line 0 = reference_type_count(control, DistRefs), + % Get rid of all references to Node + ?line exec(P, fun () -> exit(normal) end), + ?line wait_until(fun () -> not is_process_alive(P) end), + ?line case erlang:system_info(heap_type) of + shared -> + ?line garbage_collect(); + hybrid -> + ?line lists:foreach(fun (Proc) -> garbage_collect(Proc) end, + processes()), + ?line erlang:garbage_collect_message_area(); + _ -> + ?line lists:foreach(fun (Proc) -> garbage_collect(Proc) end, + processes()) + end, + ?line false = get_node_references({Node,Creation}), + ?line false = get_dist_references(Node), + ?line false = lists:member(Node, nodes(known)), + ?line nc_refc_check(node()), + ?line ok. + +%% +%% Test case: ets_refc +%% +ets_refc(doc) -> + ["Tests that external reference counts are incremented and decremented " + "as they should for data stored in ets tables."]; +ets_refc(suite) -> []; +ets_refc(Config) when is_list(Config) -> + ?line RNode = {get_nodename(), 1}, + ?line RPid = mk_pid(RNode, 4711, 2), + ?line RPort = mk_port(RNode, 4711), + ?line RRef = mk_ref(RNode, [4711, 47, 11]), + ?line Tab = ets:new(ets_refc, []), + ?line 0 = reference_type_count(ets, get_node_references(RNode)), + ?line true = ets:insert(Tab, [{a, self()}, + {b, RPid}, + {c, hd(erlang:ports())}, + {d, RPort}, + {e, make_ref()}]), + ?line 2 = reference_type_count(ets, get_node_references(RNode)), + ?line true = ets:insert(Tab, {f, RRef}), + ?line 3 = reference_type_count(ets, get_node_references(RNode)), + ?line true = ets:delete(Tab, d), + ?line 2 = reference_type_count(ets, get_node_references(RNode)), + ?line true = ets:delete_all_objects(Tab), + ?line 0 = reference_type_count(ets, get_node_references(RNode)), + ?line true = ets:insert(Tab, [{b, RPid}, {e, make_ref()}]), + ?line 1 = reference_type_count(ets, get_node_references(RNode)), + ?line true = ets:delete(Tab), + ?line 0 = reference_type_count(ets, get_node_references(RNode)), + ?line nc_refc_check(node()), + ?line ok. + +%% +%% Test case: match_spec_refc +%% +match_spec_refc(doc) -> + ["Tests that external reference counts are incremented and decremented " + "as they should for data stored in match specifications."]; +match_spec_refc(suite) -> []; +match_spec_refc(Config) when is_list(Config) -> + ?line RNode = {get_nodename(), 1}, + ?line RPid = mk_pid(RNode, 4711, 2), + ?line RPort = mk_port(RNode, 4711), + ?line RRef = mk_ref(RNode, [4711, 47, 11]), + ?line ok = do_match_spec_test(RNode, RPid, RPort, RRef), + ?line garbage_collect(), + ?line NodeRefs = get_node_references(RNode), + ?line 0 = reference_type_count(binary, NodeRefs), + ?line 0 = reference_type_count(ets, NodeRefs), + ?line nc_refc_check(node()), + ?line ok. + +do_match_spec_test(RNode, RPid, RPort, RRef) -> + ?line Tab = ets:new(match_spec_refc, []), + ?line true = ets:insert(Tab, [{a, RPid, RPort, RRef}, + {b, self(), RPort, RRef}, + {c, RPid, RPort, make_ref()}, + {d, RPid, RPort, RRef}]), + ?line {M1, C1} = ets:select(Tab, [{{'$1',RPid,RPort,RRef},[],['$1']}], 1), + ?line NodeRefs = get_node_references(RNode), + ?line 3 = reference_type_count(binary, NodeRefs), + ?line 10 = reference_type_count(ets, NodeRefs), + ?line {M2, C2} = ets:select(C1), + ?line '$end_of_table' = ets:select(C2), + ?line ets:delete(Tab), + ?line [a,d] = lists:sort(M1++M2), + ?line ok. + + +%% +%% Test case: ets_refc +%% +timer_refc(doc) -> + ["Tests that external reference counts are incremented and decremented " + "as they should for data stored in bif timers."]; +timer_refc(suite) -> []; +timer_refc(Config) when is_list(Config) -> + ?line RNode = {get_nodename(), 1}, + ?line RPid = mk_pid(RNode, 4711, 2), + ?line RPort = mk_port(RNode, 4711), + ?line RRef = mk_ref(RNode, [4711, 47, 11]), + ?line 0 = reference_type_count(timer, get_node_references(RNode)), + ?line Pid = spawn(fun () -> receive after infinity -> ok end end), + ?line erlang:start_timer(10000, Pid, {RPid, RPort, RRef}), + ?line 3 = reference_type_count(timer, get_node_references(RNode)), + ?line exit(Pid, kill), + ?line Mon = erlang:monitor(process, Pid), + ?line receive {'DOWN', Mon, process, Pid, _} -> ok end, + ?line 0 = reference_type_count(timer, get_node_references(RNode)), + ?line erlang:send_after(500, Pid, {timer, RPid, RPort, RRef}), + ?line 0 = reference_type_count(timer, get_node_references(RNode)), + ?line erlang:send_after(500, self(), {timer, RPid, RPort, RRef}), + ?line erlang:send_after(400, bananfluga, {timer, RPid, RPort, RRef}), + ?line 6 = reference_type_count(timer, get_node_references(RNode)), + ?line receive {timer, RPid, RPort, RRef} -> ok end, + ?line 0 = reference_type_count(timer, get_node_references(RNode)), + ?line nc_refc_check(node()), + ?line ok. + +otp_4715(doc) -> []; +otp_4715(suite) -> []; +otp_4715(Config) when is_list(Config) -> + case ?t:is_release_available("r9b") of + true -> otp_4715_1(Config); + false -> {skip,"No R9B found"} + end. + +otp_4715_1(Config) -> + case erlang:system_info(compat_rel) of + 9 -> + ?line run_otp_4715(Config); + _ -> + ?line Pa = filename:dirname(code:which(?MODULE)), + ?line ?t:run_on_shielded_node(fun () -> + run_otp_4715(Config) + end, + "+R9 -pa " ++ Pa) + end. + +run_otp_4715(Config) when is_list(Config) -> + ?line erts_debug:set_internal_state(available_internal_state, true), + ?line PidList = [mk_pid({a@b, 1}, 4710, 2), + mk_pid({a@b, 1}, 4712, 1), + mk_pid({c@b, 1}, 4711, 1), + mk_pid({b@b, 3}, 4711, 1), + mk_pid({b@b, 2}, 4711, 1)], + + ?line R9Sorted = old_mod:sort_on_old_node(PidList), + ?line R9Sorted = lists:sort(PidList). + +pid_wrap(doc) -> []; +pid_wrap(suite) -> []; +pid_wrap(Config) when is_list(Config) -> ?line pp_wrap(pid). + +port_wrap(doc) -> []; +port_wrap(suite) -> []; +port_wrap(Config) when is_list(Config) -> + ?line case ?t:os_type() of + {unix, _} -> + ?line pp_wrap(port); + _ -> + ?line {skip, "Only run on unix"} + end. + +get_next_id(pid) -> + erts_debug:get_internal_state(next_pid); +get_next_id(port) -> + erts_debug:get_internal_state(next_port). + +set_next_id(pid, N) -> + erts_debug:set_internal_state(next_pid, N); +set_next_id(port, N) -> + erts_debug:set_internal_state(next_port, N). + +pp_wrap(What) -> + ?line N = set_high_pp_next(What), + ?line Cre = N + 100, + ?line ?t:format("no creations = ~p~n", [Cre]), + ?line PreCre = get_next_id(What), + ?line ?t:format("pre creations = ~p~n", [PreCre]), + ?line true = is_integer(PreCre), + ?line do_pp_creations(What, Cre), + ?line PostCre = get_next_id(What), + ?line ?t:format("post creations = ~p~n", [PostCre]), + ?line true = is_integer(PostCre), + ?line true = PreCre > PostCre, + ?line Now = set_next_id(What, ?MAX_PIDS_PORTS div 2), + ?line ?t:format("reset to = ~p~n", [Now]), + ?line true = is_integer(Now), + ?line ok. + +set_high_pp_next(What) -> + ?line set_high_pp_next(What, ?MAX_PIDS_PORTS-1). + +set_high_pp_next(What, N) -> + ?line M = set_next_id(What, N), + ?line true = is_integer(M), + ?line case {M >= N, M =< ?MAX_PIDS_PORTS} of + {true, true} -> + ?line ?MAX_PIDS_PORTS - M + 1; + _ -> + ?line set_high_pp_next(What, N - 100) + end. + +do_pp_creations(_What, N) when is_integer(N), N =< 0 -> + ?line done; +do_pp_creations(pid, N) when is_integer(N) -> + %% Create new pid and make sure it works... + ?line Me = self(), + ?line Ref = make_ref(), + ?line Pid = spawn_link(fun () -> + receive + Ref -> + Me ! Ref + end + end), + ?line Pid ! Ref, + ?line receive + Ref -> + ?line do_pp_creations(pid, N - 1) + end; +do_pp_creations(port, N) when is_integer(N) -> + %% Create new port and make sure it works... + ?line "hej" = os:cmd("echo hej") -- "\n", + ?line do_pp_creations(port, N - 1). + +bad_nc(doc) -> []; +bad_nc(suite) -> []; +bad_nc(Config) when is_list(Config) -> + % Make sure emulator don't crash on bad node containers... + ?line MaxPidNum = (1 bsl 15) - 1, + ?line MaxPidSer = ?MAX_PIDS_PORTS bsr 15, + ?line ThisNode = {node(), erlang:system_info(creation)}, + ?line {'EXIT', {badarg, mk_pid, _}} + = (catch mk_pid(ThisNode, MaxPidNum + 1, 17)), + ?line {'EXIT', {badarg, mk_pid, _}} + = (catch mk_pid(ThisNode, 4711, MaxPidSer + 1)), + ?line {'EXIT', {badarg, mk_port, _}} + = (catch mk_port(ThisNode, ?MAX_PIDS_PORTS + 1)), + ?line {'EXIT', {badarg, mk_ref, _}} + = (catch mk_ref(ThisNode,[(1 bsl 18), 4711, 4711])), + ?line {'EXIT', {badarg, mk_ref, _}} + = (catch mk_ref(ThisNode, [4711, 4711, 4711, 4711, 4711, 4711, 4711])), + ?line RemNode = {x@y, 2}, + ?line {'EXIT', {badarg, mk_pid, _}} + = (catch mk_pid(RemNode, MaxPidNum + 1, MaxPidSer)), + ?line {'EXIT', {badarg, mk_pid, _}} + = (catch mk_pid(RemNode, MaxPidNum, MaxPidSer + 1)), + ?line {'EXIT', {badarg, mk_port, _}} + = (catch mk_port(RemNode, ?MAX_PIDS_PORTS + 1)), + ?line {'EXIT', {badarg, mk_ref, _}} + = (catch mk_ref(RemNode, [(1 bsl 18), 4711, 4711])), + ?line {'EXIT', {badarg, mk_ref, _}} + = (catch mk_ref(RemNode, [4711, 4711, 4711, 4711, 4711, 4711, 4711])), + ?line BadNode = {x@y, 4}, + ?line {'EXIT', {badarg, mk_pid, _}} + = (catch mk_pid(BadNode, 4711, 17)), + ?line {'EXIT', {badarg, mk_port, _}} + = (catch mk_port(BadNode, 4711)), + ?line {'EXIT', {badarg, mk_ref, _}} + = (catch mk_ref(BadNode, [4711, 4711, 17])), + ?line ok. + + + +-define(NO_PIDS, 1000000). + +unique_pid(doc) -> []; +unique_pid(suite) -> []; +unique_pid(Config) when is_list(Config) -> + case catch erlang:system_info(modified_timing_level) of + Level when is_integer(Level) -> + {skip, + "Modified timing (level " ++ integer_to_list(Level) + ++ ") is enabled. spawn() is too slow for this " + " test when modified timing is enabled."}; + _ -> + ?line ?NO_PIDS = length(lists:usort(mkpidlist(?NO_PIDS, []))), + ?line ok + end. + +mkpidlist(0, Ps) -> Ps; +mkpidlist(N, Ps) -> mkpidlist(N-1, [spawn(fun () -> ok end)|Ps]). + + +iter_max_procs(doc) -> []; +iter_max_procs(suite) -> []; +iter_max_procs(Config) when is_list(Config) -> + ?line NoMoreTests = make_ref(), + ?line erlang:send_after(10000, self(), NoMoreTests), + ?line Res = chk_max_proc_line(), + ?line Res = chk_max_proc_line(), + ?line done = chk_max_proc_line_until(NoMoreTests, Res), + ?line {comment, + io_lib:format("max processes = ~p; " + "process line length = ~p", + [element(2, Res), element(1, Res)])}. + + +max_proc_line(Root, Parent, N) -> + Me = self(), + case catch spawn_link(fun () -> max_proc_line(Root, Me, N+1) end) of + {'EXIT', {system_limit, _}} when Root /= self() -> + Root ! {proc_line_length, N, self()}, + receive remove_proc_line -> Parent ! {exiting, Me} end; + P when is_pid(P), Root =/= self() -> + receive {exiting, P} -> Parent ! {exiting, Me} end; + P when is_pid(P) -> + P; + Unexpected -> + exit({unexpected_spawn_result, Unexpected}) + end. + +chk_max_proc_line() -> + ?line Child = max_proc_line(self(), self(), 0), + ?line receive + {proc_line_length, PLL, End} -> + ?line PC = erlang:system_info(process_count), + ?line LP = length(processes()), + ?line ?t:format("proc line length = ~p; " + "process count = ~p; " + "length processes = ~p~n", + [PLL, PC, LP]), + ?line End ! remove_proc_line, + ?line PC = LP, + ?line receive {exiting, Child} -> ok end, + ?line {PLL, PC} + end. + +chk_max_proc_line_until(NoMoreTests, Res) -> + receive + NoMoreTests -> + ?line done + after 0 -> + ?line Res = chk_max_proc_line(), + ?line chk_max_proc_line_until(NoMoreTests, Res) + end. + +%% +%% -- Internal utils --------------------------------------------------------- +%% + +-define(ND_REFS, erts_debug:get_internal_state(node_and_dist_references)). + +node_container_refc_check(Node) when is_atom(Node) -> + AIS = available_internal_state(true), + nc_refc_check(Node), + available_internal_state(AIS). + +nc_refc_check(Node) when is_atom(Node) -> + Ref = make_ref(), + Self = self(), + ?t:format("Starting reference count check of node ~w~n", [Node]), + spawn_link(Node, + fun () -> + {{node_references, NodeRefs}, + {dist_references, DistRefs}} = ?ND_REFS, + check_nd_refc({node(), erlang:system_info(creation)}, + NodeRefs, + DistRefs, + fun (ErrMsg) -> + Self ! {Ref, ErrMsg, failed}, + exit(normal) + end), + Self ! {Ref, succeded} + end), + receive + {Ref, ErrorMsg, failed} -> + ?t:format("~s~n", [ErrorMsg]), + ?t:fail(reference_count_check_failed); + {Ref, succeded} -> + ?t:format("Reference count check of node ~w succeded!~n", [Node]), + ok + end. + +check_nd_refc({ThisNodeName, ThisCreation}, NodeRefs, DistRefs, Fail) -> + case catch begin + check_refc(ThisNodeName,ThisCreation,"node table",NodeRefs), + check_refc(ThisNodeName,ThisCreation,"dist table",DistRefs), + ok + end of + ok -> + ok; + {'EXIT', Reason} -> + {Y,Mo,D} = date(), + {H,Mi,S} = time(), + ErrMsg = io_lib:format("~n" + "*** Reference count check of node ~w " + "failed (~p) at ~w~w~w ~w:~w:~w~n" + "*** Node table references:~n ~p~n" + "*** Dist table references:~n ~p~n", + [node(), Reason, Y, Mo, D, H, Mi, S, + NodeRefs, DistRefs]), + Fail(lists:flatten(ErrMsg)) + end. + + +check_refc(ThisNodeName,ThisCreation,Table,EntryList) when is_list(EntryList) -> + lists:foreach( + fun ({Entry, Refc, ReferrerList}) -> + FoundRefs = + lists:foldl( + fun ({_Referrer, ReferencesList}, A1) -> + A1 + lists:foldl(fun ({_T,Rs},A2) -> + A2+Rs + end, + 0, + ReferencesList) + end, + 0, + ReferrerList), + + %% Reference count equals found references ? + case Refc =:= FoundRefs of + true -> + ok; + false -> + exit({invalid_reference_count, Table, Entry}) + end, + + %% All entries in table referred to? + case {Entry, Refc} of + {ThisNodeName, 0} -> ok; + {{ThisNodeName, ThisCreation}, 0} -> ok; + {_, 0} -> exit({not_referred_entry_in_table, Table, Entry}); + {_, _} -> ok + end + + end, + EntryList), + ok. + +get_node_references({NodeName, Creation} = Node) when is_atom(NodeName), + is_integer(Creation) -> + {{node_references, NodeRefs}, + {dist_references, DistRefs}} = ?ND_REFS, + check_nd_refc({node(), erlang:system_info(creation)}, + NodeRefs, + DistRefs, + fun (ErrMsg) -> + ?t:format("~s", [ErrMsg]), + ?t:fail(reference_count_check_failed) + end), + find_references(Node, NodeRefs). + +get_dist_references(NodeName) when is_atom(NodeName) -> + ?line {{node_references, NodeRefs}, + {dist_references, DistRefs}} = ?ND_REFS, + ?line check_nd_refc({node(), erlang:system_info(creation)}, + NodeRefs, + DistRefs, + fun (ErrMsg) -> + ?line ?t:format("~s", [ErrMsg]), + ?line ?t:fail(reference_count_check_failed) + end), + ?line find_references(NodeName, DistRefs). + +find_references(N, NRefList) -> + case lists:keysearch(N, 1, NRefList) of + {value, {N, _, ReferrersList}} -> ReferrersList; + _ -> false + end. + +%% Currently unused +% refering_entity_type(RefererType, ReferingEntities) -> +% lists:filter(fun ({{RT, _}, _}) when RT == RefererType -> +% true; +% (_) -> +% false +% end, +% ReferingEntities). + +refering_entity_id(ReferingEntityId, [{ReferingEntityId,_} = ReferingEntity + | _ReferingEntities]) -> + ReferingEntity; +refering_entity_id(ReferingEntityId, [_ | ReferingEntities]) -> + refering_entity_id(ReferingEntityId, ReferingEntities); +refering_entity_id(_, []) -> + false. + +reference_type_count(_, false) -> + 0; +reference_type_count(Type, {_, _ReferenceCountList} = ReferingEntity) -> + reference_type_count(Type, [ReferingEntity]); +reference_type_count(Type, ReferingEntities) when is_list(ReferingEntities) -> + lists:foldl(fun ({_, ReferenceCountList}, Acc1) -> + lists:foldl(fun ({T, N}, Acc2) when T == Type -> + N + Acc2; + (_, Acc2) -> + Acc2 + end, + Acc1, + ReferenceCountList) + end, + 0, + ReferingEntities). + + +start_node(Name, Args) -> + ?line Pa = filename:dirname(code:which(?MODULE)), + ?line Res = test_server:start_node(Name, + slave, + [{args, "-pa "++Pa++" "++Args}]), + ?line {ok, Node} = Res, + ?line rpc:call(Node, erts_debug, set_internal_state, + [available_internal_state, true]), + ?line Res. + +start_node(Name) -> + ?line start_node(Name, ""). + +stop_node(Node) -> + ?line nc_refc_check(Node), + ?line true = test_server:stop_node(Node). + +hostname() -> + from($@, atom_to_list(node())). + +from(H, [H | T]) -> T; +from(H, [_ | T]) -> from(H, T); +from(_H, []) -> []. + +wait_until(Pred) -> + case Pred() of + true -> ok; + false -> receive after 100 -> wait_until(Pred) end + end. + + +get_nodefirstname() -> + {A, B, C} = now(), + list_to_atom(atom_to_list(?MODULE) + ++ "-" + ++ integer_to_list(A) + ++ "-" + ++ integer_to_list(B) + ++ "-" + ++ integer_to_list(C)). + +get_nodename() -> + {A, B, C} = now(), + list_to_atom(atom_to_list(?MODULE) + ++ "-" + ++ integer_to_list(A) + ++ "-" + ++ integer_to_list(B) + ++ "-" + ++ integer_to_list(C) + ++ "@" + ++ hostname()). + + + +-define(VERSION_MAGIC, 131). + +-define(ATOM_EXT, 100). +-define(REFERENCE_EXT, 101). +-define(PORT_EXT, 102). +-define(PID_EXT, 103). +-define(NEW_REFERENCE_EXT, 114). + +uint32_be(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 32 -> + [(Uint bsr 24) band 16#ff, + (Uint bsr 16) band 16#ff, + (Uint bsr 8) band 16#ff, + Uint band 16#ff]; +uint32_be(Uint) -> + exit({badarg, uint32_be, [Uint]}). + + +uint16_be(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 16 -> + [(Uint bsr 8) band 16#ff, + Uint band 16#ff]; +uint16_be(Uint) -> + exit({badarg, uint16_be, [Uint]}). + +uint8(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 8 -> + Uint band 16#ff; +uint8(Uint) -> + exit({badarg, uint8, [Uint]}). + + + +mk_pid({NodeName, Creation}, Number, Serial) when is_atom(NodeName) -> + mk_pid({atom_to_list(NodeName), Creation}, Number, Serial); +mk_pid({NodeName, Creation}, Number, Serial) -> + case catch binary_to_term(list_to_binary([?VERSION_MAGIC, + ?PID_EXT, + ?ATOM_EXT, + uint16_be(length(NodeName)), + NodeName, + uint32_be(Number), + uint32_be(Serial), + uint8(Creation)])) of + Pid when is_pid(Pid) -> + Pid; + {'EXIT', {badarg, _}} -> + exit({badarg, mk_pid, [{NodeName, Creation}, Number, Serial]}); + Other -> + exit({unexpected_binary_to_term_result, Other}) + end. + +mk_port({NodeName, Creation}, Number) when is_atom(NodeName) -> + mk_port({atom_to_list(NodeName), Creation}, Number); +mk_port({NodeName, Creation}, Number) -> + case catch binary_to_term(list_to_binary([?VERSION_MAGIC, + ?PORT_EXT, + ?ATOM_EXT, + uint16_be(length(NodeName)), + NodeName, + uint32_be(Number), + uint8(Creation)])) of + Port when is_port(Port) -> + Port; + {'EXIT', {badarg, _}} -> + exit({badarg, mk_port, [{NodeName, Creation}, Number]}); + Other -> + exit({unexpected_binary_to_term_result, Other}) + end. + +mk_ref({NodeName, Creation}, Numbers) when is_atom(NodeName), + is_integer(Creation), + is_list(Numbers) -> + mk_ref({atom_to_list(NodeName), Creation}, Numbers); +mk_ref({NodeName, Creation}, [Number]) when is_list(NodeName), + is_integer(Creation), + is_integer(Number) -> + case catch binary_to_term(list_to_binary([?VERSION_MAGIC, + ?REFERENCE_EXT, + ?ATOM_EXT, + uint16_be(length(NodeName)), + NodeName, + uint32_be(Number), + uint8(Creation)])) of + Ref when is_reference(Ref) -> + Ref; + {'EXIT', {badarg, _}} -> + exit({badarg, mk_ref, [{NodeName, Creation}, [Number]]}); + Other -> + exit({unexpected_binary_to_term_result, Other}) + end; +mk_ref({NodeName, Creation}, Numbers) when is_list(NodeName), + is_integer(Creation), + is_list(Numbers) -> + case catch binary_to_term(list_to_binary([?VERSION_MAGIC, + ?NEW_REFERENCE_EXT, + uint16_be(length(Numbers)), + ?ATOM_EXT, + uint16_be(length(NodeName)), + NodeName, + uint8(Creation), + lists:map(fun (N) -> + uint32_be(N) + end, + Numbers)])) of + Ref when is_reference(Ref) -> + Ref; + {'EXIT', {badarg, _}} -> + exit({badarg, mk_ref, [{NodeName, Creation}, Numbers]}); + Other -> + exit({unexpected_binary_to_term_result, Other}) + end. + +exec_loop() -> + receive + {exec_fun, Fun} when is_function(Fun) -> + Fun(); + {sync_exec_fun, From, Fun} when is_pid(From), is_function(Fun) -> + From ! {sync_exec_fun_res, self(), Fun()} + end, + exec_loop(). + +spawn_execer(Node) -> + spawn(Node, fun () -> exec_loop() end). + +spawn_link_execer(Node) -> + spawn_link(Node, fun () -> exec_loop() end). + +exec(Pid, Fun) when is_pid(Pid), is_function(Fun) -> + Pid ! {exec_fun, Fun}. + +sync_exec(Pid, Fun) when is_pid(Pid), is_function(Fun) -> + Pid ! {sync_exec_fun, self(), Fun}, + receive + {sync_exec_fun_res, Pid, Res} -> + Res + end. diff --git a/erts/emulator/test/nofrag_SUITE.erl b/erts/emulator/test/nofrag_SUITE.erl new file mode 100644 index 0000000000..ece55f433c --- /dev/null +++ b/erts/emulator/test/nofrag_SUITE.erl @@ -0,0 +1,208 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(nofrag_SUITE). + +-include("test_server.hrl"). + +-export([all/1,init_per_testcase/2,end_per_testcase/2, + error_handler/1,error_handler_apply/1, + error_handler_fixed_apply/1,error_handler_fun/1, + error_handler_tuple_fun/1, + debug_breakpoint/1]). + +%% Exported functions for an error_handler module. +-export([undefined_function/3,undefined_lambda/3,breakpoint/3]). + +all(suite) -> + [error_handler,error_handler_apply,error_handler_fixed_apply, + error_handler_fun,error_handler_tuple_fun,debug_breakpoint]. + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog = ?t:timetrap(?t:minutes(3)), + [{watchdog,Dog}|Config]. + +end_per_testcase(_Func, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +error_handler(Config) when is_list(Config) -> + ?line process_flag(error_handler, ?MODULE), + %% The term_to_binary/1 - binary_to_term/1 roundtrip is a good way + %% to traverse the entire term. + ?line Term = collect(1024), + ?line Term = binary_to_term(term_to_binary(Term)), + ?line 1024 = length(Term), + ?line [[a,b,c,d,[e,f,g]]] = lists:usort(Term), + ok. + +collect(0) -> + []; +collect(N) -> + %% The next line calls the error handle function, which is + %% ?MODULE:undefined_function/3 (it simply returns the list + %% of args, i.e. [a,b,c,d,[e,f,g]]). + C = fooblurf:x(a, b, c, d, [e,f,id(g)]), + + %% The variable C will be saved onto the stack frame; if C + %% points into a heap fragment the garbage collector will reach + %% it and the emulator will crash sooner or later (sooner if + %% the emulator is debug-compiled). + Res = collect(N-1), + [C|Res]. + +collect_apply(0, _) -> + []; +collect_apply(N, Mod) -> + %% The next line calls the error handle function, which is + %% ?MODULE:undefined_function/3 (it simply returns the list + %% of args). + + C = apply(Mod, xyz, id([{a,id(42)},b,c,d,[e,f,id(g)]])), + + %% The variable C will be saved onto the stack frame; if C + %% points into a heap fragment the garbage collector will reach + %% it and the emulator will crash sooner or later (sooner if + %% the emulator is debug-compiled). + Res = collect_apply(N-1, Mod), + [C|Res]. + +error_handler_apply(Config) when is_list(Config) -> + ?line process_flag(error_handler, ?MODULE), + + %% The term_to_binary/1 - binary_to_term/1 roundtrip is a good way + %% to traverse the entire term. + ?line Term = collect_apply(1024, fooblurfbar), + ?line Term = binary_to_term(term_to_binary(Term)), + ?line 1024 = length(Term), + ?line [[{a,42},b,c,d,[e,f,g]]] = lists:usort(Term), + ok. + +error_handler_fixed_apply(Config) when is_list(Config) -> + ?line process_flag(error_handler, ?MODULE), + + %% The term_to_binary/1 - binary_to_term/1 roundtrip is a good way + %% to traverse the entire term. + ?line Term = collect_fixed_apply(1024, fooblurfbar), + ?line Term = binary_to_term(term_to_binary(Term)), + ?line 1024 = length(Term), + ?line [[{a,2},b,c,d,[e,f,g]]] = lists:usort(Term), + ok. + +collect_fixed_apply(0, _) -> + []; +collect_fixed_apply(N, Mod) -> + %% The next line calls the error handle function, which is + %% ?MODULE:undefined_function/3 (it simply returns the list + %% of args). + C = Mod:x({a,id(2)}, b, c, d, [e,f,id(g)]), + + %% The variable C will be saved onto the stack frame; if C + %% points into a heap fragment the garbage collector will reach + %% it and the emulator will crash sooner or later (sooner if + %% the emulator is debug-compiled). + Res = collect_fixed_apply(N-1, Mod), + [C|Res]. + +undefined_function(_Mod, _Name, Args) -> + Args. + +error_handler_fun(Config) when is_list(Config) -> + ?line process_flag(error_handler, ?MODULE), + + %% fun(A, B, C) -> {A,B,C,X} end in module foobarblurf. + B = <<131,112,0,0,0,84,3,109,96,69,208,5,175,207,75,36,93,112,218,232,222,22,251,0, + 0,0,0,0,0,0,1,100,0,11,102,111,111,98,97,114,98,108,117,114,102,97,0,98,5, + 244,197,144,103,100,0,13,110,111,110,111,100,101,64,110,111,104,111,115,116, + 0,0,0,46,0,0,0,0,0,104,3,97,1,97,2,97,3>>, + ?line Fun = binary_to_term(B), + ?line Term = collect_fun(1024, Fun), + ?line Term = binary_to_term(term_to_binary(Term)), + ?line 1024 = length(Term), + ?line [[{foo,bar},{99,1.0},[e,f,g]]] = lists:usort(Term), + ?line {env,[{1,2,3}]} = erlang:fun_info(Fun, env), + ok. + +collect_fun(0, _) -> + []; +collect_fun(N, Fun) -> + %% The next line calls the error handle function, which is + %% ?MODULE:undefined_lambda/3 (it simply returns the list + %% of args). + C = Fun({foo,id(bar)}, {99,id(1.0)}, [e,f,id(g)]), + + %% The variable C will be saved onto the stack frame; if C + %% points into a heap fragment the garbage collector will reach + %% it and the emulator will crash sooner or later (sooner if + %% the emulator is debug-compiled). + Res = collect_fun(N-1, Fun), + [C|Res]. + +undefined_lambda(foobarblurf, Fun, Args) when is_function(Fun) -> + Args. + +error_handler_tuple_fun(Config) when is_list(Config) -> + ?line process_flag(error_handler, ?MODULE), + ?line Term = collect_tuple_fun(1024, {?MODULE,very_undefined_function}), + ?line Term = binary_to_term(term_to_binary(Term)), + ?line 1024 = length(Term), + ?line [[{foo,bar},42.0,[e,f,g]]] = lists:usort(Term), + ok. + +collect_tuple_fun(0, _) -> + []; +collect_tuple_fun(N, Fun) -> + %% The next line calls the error handle function, which is + %% ?MODULE:undefined_function/3 (it simply returns the list + %% of args). + C = Fun({foo,id(bar)}, 42.0, [e,f,id(g)]), + + %% The variable C will be saved onto the stack frame; if C + %% points into a heap fragment the garbage collector will reach + %% it and the emulator will crash sooner or later (sooner if + %% the emulator is debug-compiled). + Res = collect_tuple_fun(N-1, Fun), + [C|Res]. + +debug_breakpoint(Config) when is_list(Config) -> + ?line process_flag(error_handler, ?MODULE), + ?line erts_debug:breakpoint({?MODULE,foobar,5}, true), + ?line Term = break_collect(1024), + ?line Term = binary_to_term(term_to_binary(Term)), + ?line 1024 = length(Term), + ?line [[a,b,c,{d,e},[f,g,h]]] = lists:usort(Term), + ?line erts_debug:breakpoint({?MODULE,foobar,5}, false), + ok. + +break_collect(0) -> + []; +break_collect(N) -> + C = foobar(a, b, c, {id(d),e}, [f,g,id(h)]), + Res = break_collect(N-1), + [C|Res]. + +breakpoint(?MODULE, foobar, Args) -> + Args. + +foobar(_, _, _, _, _) -> + exit(dont_execute_me). + +id(I) -> I. + + diff --git a/erts/emulator/test/num_bif_SUITE.erl b/erts/emulator/test/num_bif_SUITE.erl new file mode 100644 index 0000000000..d009994e2d --- /dev/null +++ b/erts/emulator/test/num_bif_SUITE.erl @@ -0,0 +1,268 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(num_bif_SUITE). + +-include("test_server.hrl"). + +%% Tests the BIFs: +%% abs/1 +%% float/1 +%% float_to_list/1 +%% integer_to_list/1 +%% list_to_float/1 +%% list_to_integer/1 +%% round/1 +%% trunc/1 + +-export([all/1, t_abs/1, t_float/1, + t_float_to_list/1, t_integer_to_list/1, + t_list_to_integer/1, + t_list_to_float/1, t_list_to_float_safe/1, t_list_to_float_risky/1, + t_round/1, t_trunc/1]). + +all(suite) -> [t_abs, t_float, t_float_to_list, t_integer_to_list, + t_list_to_float, t_list_to_integer, + t_round, t_trunc]. + +t_abs(Config) when is_list(Config) -> + %% Floats. + ?line 5.5 = abs(id(5.5)), + ?line 0.0 = abs(id(0.0)), + ?line 100.0 = abs(id(-100.0)), + + %% Integers. + ?line 5 = abs(id(5)), + ?line 0 = abs(id(0)), + ?line 100 = abs(id(-100)), + + %% The largest smallnum. OTP-3190. + ?line X = id((1 bsl 27) - 1), + ?line X = abs(X), + ?line X = abs(X-1)+1, + ?line X = abs(X+1)-1, + ?line X = abs(-X), + ?line X = abs(-X-1)-1, + ?line X = abs(-X+1)+1, + + %% Bignums. + BigNum = id(13984792374983749), + ?line BigNum = abs(BigNum), + ?line BigNum = abs(-BigNum), + ok. + +t_float(Config) when is_list(Config) -> + ?line 0.0 = float(id(0)), + ?line 2.5 = float(id(2.5)), + ?line 0.0 = float(id(0.0)), + ?line -100.55 = float(id(-100.55)), + ?line 42.0 = float(id(42)), + ?line -100.0 = float(id(-100)), + + %% Bignums. + ?line 4294967305.0 = float(id(4294967305)), + ?line -4294967305.0 = float(id(-4294967305)), + + %% Extremly big bignums. + ?line Big = id(list_to_integer(id(lists:duplicate(2000, $1)))), + ?line {'EXIT', {badarg, _}} = (catch float(Big)), + + %% Invalid types and lists. + ?line {'EXIT', {badarg, _}} = (catch list_to_integer(id(atom))), + ?line {'EXIT', {badarg, _}} = (catch list_to_integer(id(123))), + ?line {'EXIT', {badarg, _}} = (catch list_to_integer(id([$1,[$2]]))), + ?line {'EXIT', {badarg, _}} = (catch list_to_integer(id("1.2"))), + ?line {'EXIT', {badarg, _}} = (catch list_to_integer(id("a"))), + ?line {'EXIT', {badarg, _}} = (catch list_to_integer(id(""))), + ok. + + +%% Tests float_to_list/1. + +t_float_to_list(Config) when is_list(Config) -> + ?line test_ftl("0.0e+0", 0.0), + ?line test_ftl("2.5e+1", 25.0), + ?line test_ftl("2.5e+0", 2.5), + ?line test_ftl("2.5e-1", 0.25), + ?line test_ftl("-3.5e+17", -350.0e15), + ok. + +test_ftl(Expect, Float) -> + %% No ?line on the next line -- we want the line number from t_float_to_list. + Expect = remove_zeros(lists:reverse(float_to_list(Float)), []). + +%% Removes any non-significant zeros in a floating point number. +%% Example: 2.500000e+01 -> 2.5e+1 + +remove_zeros([$+, $e|Rest], [$0, X|Result]) -> + remove_zeros([$+, $e|Rest], [X|Result]); +remove_zeros([$-, $e|Rest], [$0, X|Result]) -> + remove_zeros([$-, $e|Rest], [X|Result]); +remove_zeros([$0, $.|Rest], [$e|Result]) -> + remove_zeros(Rest, [$., $0, $e|Result]); +remove_zeros([$0|Rest], [$e|Result]) -> + remove_zeros(Rest, [$e|Result]); +remove_zeros([Char|Rest], Result) -> + remove_zeros(Rest, [Char|Result]); +remove_zeros([], Result) -> + Result. + +%% Tests integer_to_list/1. + +t_integer_to_list(Config) when is_list(Config) -> + ?line "0" = integer_to_list(id(0)), + ?line "42" = integer_to_list(id(42)), + ?line "-42" = integer_to_list(id(-42)), + ?line "32768" = integer_to_list(id(32768)), + ?line "268435455" = integer_to_list(id(268435455)), + ?line "-268435455" = integer_to_list(id(-268435455)), + ?line "123456932798748738738" = integer_to_list(id(123456932798748738738)), + ?line Big_List = id(lists:duplicate(2000, id($1))), + ?line Big = list_to_integer(Big_List), + ?line Big_List = integer_to_list(Big), + ok. + +%% Tests list_to_float/1. + +t_list_to_float(suite) -> [t_list_to_float_safe, t_list_to_float_risky]. + +t_list_to_float_safe(Config) when is_list(Config) -> + ?line 0.0 = list_to_float(id("0.0")), + ?line 0.0 = list_to_float(id("-0.0")), + ?line 0.5 = list_to_float(id("0.5")), + ?line -0.5 = list_to_float(id("-0.5")), + ?line 100.0 = list_to_float(id("1.0e2")), + ?line 127.5 = list_to_float(id("127.5")), + ?line -199.5 = list_to_float(id("-199.5")), + + ?line {'EXIT',{badarg,_}} = (catch list_to_float(id("0"))), + ?line {'EXIT',{badarg,_}} = (catch list_to_float(id("0..0"))), + ?line {'EXIT',{badarg,_}} = (catch list_to_float(id("0e12"))), + ?line {'EXIT',{badarg,_}} = (catch list_to_float(id("--0.0"))), + + ok. + +%% This might crash the emulator... +%% (Known to crash the Unix version of Erlang 4.4.1) + +t_list_to_float_risky(Config) when is_list(Config) -> + ?line Many_Ones = lists:duplicate(25000, id($1)), + ?line id(list_to_float("2."++Many_Ones)), + ?line {'EXIT', {badarg, _}} = (catch list_to_float("2"++Many_Ones)), + ok. + +%% Tests list_to_integer/1. + +t_list_to_integer(Config) when is_list(Config) -> + ?line 0 = list_to_integer(id("0")), + ?line 0 = list_to_integer(id("00")), + ?line 0 = list_to_integer(id("-0")), + ?line 1 = list_to_integer(id("1")), + ?line -1 = list_to_integer(id("-1")), + ?line 42 = list_to_integer(id("42")), + ?line -12 = list_to_integer(id("-12")), + ?line 32768 = list_to_integer(id("32768")), + ?line 268435455 = list_to_integer(id("268435455")), + ?line -268435455 = list_to_integer(id("-268435455")), + + %% Bignums. + ?line 123456932798748738738 = list_to_integer(id("123456932798748738738")), + ?line id(list_to_integer(lists:duplicate(2000, id($1)))), + ok. + +%% Tests round/1. + +t_round(Config) when is_list(Config) -> + ?line 0 = round(id(0.0)), + ?line 0 = round(id(0.4)), + ?line 1 = round(id(0.5)), + ?line 0 = round(id(-0.4)), + ?line -1 = round(id(-0.5)), + ?line 255 = round(id(255.3)), + ?line 256 = round(id(255.6)), + ?line -1033 = round(id(-1033.3)), + ?line -1034 = round(id(-1033.6)), + + % OTP-3722: + ?line X = id((1 bsl 27) - 1), + ?line MX = -X, + ?line MXm1 = -X-1, + ?line MXp1 = -X+1, + ?line F = id(X + 0.0), + ?line X = round(F), + ?line X = round(F+1)-1, + ?line X = round(F-1)+1, + ?line MX = round(-F), + ?line MXm1 = round(-F-1), + ?line MXp1 = round(-F+1), + + ?line X = round(F+0.1), + ?line X = round(F+1+0.1)-1, + ?line X = round(F-1+0.1)+1, + ?line MX = round(-F+0.1), + ?line MXm1 = round(-F-1+0.1), + ?line MXp1 = round(-F+1+0.1), + + ?line X = round(F-0.1), + ?line X = round(F+1-0.1)-1, + ?line X = round(F-1-0.1)+1, + ?line MX = round(-F-0.1), + ?line MXm1 = round(-F-1-0.1), + ?line MXp1 = round(-F+1-0.1), + + ?line 0.5 = abs(round(F+0.5)-(F+0.5)), + ?line 0.5 = abs(round(F-0.5)-(F-0.5)), + ?line 0.5 = abs(round(-F-0.5)-(-F-0.5)), + ?line 0.5 = abs(round(-F+0.5)-(-F+0.5)), + + %% Bignums. + ?line 4294967296 = round(id(4294967296.1)), + ?line 4294967297 = round(id(4294967296.9)), + ?line -4294967296 = -round(id(4294967296.1)), + ?line -4294967297 = -round(id(4294967296.9)), + ok. + +t_trunc(Config) when is_list(Config) -> + ?line 0 = trunc(id(0.0)), + ?line 5 = trunc(id(5.3333)), + ?line -10 = trunc(id(-10.978987)), + + % The largest smallnum, converted to float (OTP-3722): + ?line X = id((1 bsl 27) - 1), + ?line F = id(X + 0.0), + io:format("X = ~p/~w/~w, F = ~p/~w/~w, trunc(F) = ~p/~w/~w~n", + [X, X, binary_to_list(term_to_binary(X)), + F, F, binary_to_list(term_to_binary(F)), + trunc(F), trunc(F), binary_to_list(term_to_binary(trunc(F)))]), + ?line X = trunc(F), + ?line X = trunc(F+1)-1, + ?line X = trunc(F-1)+1, + ?line X = -trunc(-F), + ?line X = -trunc(-F-1)-1, + ?line X = -trunc(-F+1)+1, + + %% Bignums. + ?line 4294967305 = trunc(id(4294967305.7)), + ?line -4294967305 = trunc(id(-4294967305.7)), + ok. + +% Calling this function (which is not supposed to be inlined) prevents +% the compiler from calculating the answer, so we don't test the compiler +% instead of the newest runtime system. +id(X) -> X. diff --git a/erts/emulator/test/obsolete_SUITE.erl b/erts/emulator/test/obsolete_SUITE.erl new file mode 100644 index 0000000000..33c4726699 --- /dev/null +++ b/erts/emulator/test/obsolete_SUITE.erl @@ -0,0 +1,123 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + + +-module(obsolete_SUITE). +-author('[email protected]'). +-compile(nowarn_obsolete_guard). + +-export([all/1]). + +-export([erl_threads/1]). + +-include("test_server.hrl"). + +-define(DEFAULT_TIMETRAP_SECS, 240). + +all(doc) -> []; +all(suite) -> + case catch erlang:system_info(wordsize) of + 4 -> [erl_threads]; + _ -> {skip, "Only expected to work on 32-bit architectures"} + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %% +%% Testcases %% +%% %% + +erl_threads(suite) -> []; +erl_threads(doc) -> []; +erl_threads(Cfg) -> + ?line case erlang:system_info(threads) of + true -> + ?line drv_case(Cfg, erl_threads); + false -> + ?line {skip, "Emulator not compiled with threads support"} + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %% +%% Internal functions %% +%% %% + +drv_case(Config, CaseName) -> + drv_case(Config, CaseName, ""). + +drv_case(Config, CaseName, TimeTrap) when integer(TimeTrap) -> + drv_case(Config, CaseName, "", TimeTrap); +drv_case(Config, CaseName, Command) when list(Command) -> + drv_case(Config, CaseName, Command, ?DEFAULT_TIMETRAP_SECS). + +drv_case(Config, CaseName, TimeTrap, Command) when list(Command), + integer(TimeTrap) -> + drv_case(Config, CaseName, Command, TimeTrap); +drv_case(Config, CaseName, Command, TimeTrap) when list(Config), + atom(CaseName), + list(Command), + integer(TimeTrap) -> + case ?t:os_type() of + {Family, _} when Family == unix; Family == win32 -> + ?line run_drv_case(Config, CaseName, Command, TimeTrap); + SkipOs -> + ?line {skipped, + lists:flatten(["Not run on " + | io_lib:format("~p",[SkipOs])])} + end. + +run_drv_case(Config, CaseName, Command, TimeTrap) -> + ?line Dog = test_server:timetrap(test_server:seconds(TimeTrap)), + ?line DataDir = ?config(data_dir,Config), + case erl_ddll:load_driver(DataDir, CaseName) of + ok -> ok; + {error, Error} -> + io:format("~s\n", [erl_ddll:format_error(Error)]), + ?line ?t:fail() + end, + ?line Port = open_port({spawn, atom_to_list(CaseName)}, []), + ?line true = is_port(Port), + ?line Port ! {self(), {command, Command}}, + ?line Result = receive_drv_result(Port, CaseName), + ?line Port ! {self(), close}, + ?line receive + {Port, closed} -> + ok + end, + ?line ok = erl_ddll:unload_driver(CaseName), + ?line test_server:timetrap_cancel(Dog), + ?line Result. + +receive_drv_result(Port, CaseName) -> + ?line receive + {print, Port, CaseName, Str} -> + ?line ?t:format("~s", [Str]), + ?line receive_drv_result(Port, CaseName); + {'EXIT', Port, Error} -> + ?line ?t:fail(Error); + {'EXIT', error, Error} -> + ?line ?t:fail(Error); + {failed, Port, CaseName, Comment} -> + ?line ?t:fail(Comment); + {skipped, Port, CaseName, Comment} -> + ?line {skipped, Comment}; + {succeeded, Port, CaseName, ""} -> + ?line succeeded; + {succeeded, Port, CaseName, Comment} -> + ?line {comment, Comment} + end. diff --git a/erts/emulator/test/obsolete_SUITE_data/Makefile.src b/erts/emulator/test/obsolete_SUITE_data/Makefile.src new file mode 100644 index 0000000000..d8e2b861c0 --- /dev/null +++ b/erts/emulator/test/obsolete_SUITE_data/Makefile.src @@ -0,0 +1,33 @@ +# ``The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved via the world wide web at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# The Initial Developer of the Original Code is Ericsson Utvecklings AB. +# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings +# AB. All Rights Reserved.'' +# +# $Id$ +# + +TEST_DRVS = erl_threads@dll@ +CC = @CC@ +LD = @LD@ +CFLAGS = @SHLIB_CFLAGS@ -I@erl_include@ @DEFS@ +SHLIB_EXTRA_LDLIBS = testcase_driver@obj@ + +all: $(TEST_DRVS) + +@SHLIB_RULES@ + +testcase_driver@obj@: testcase_driver.c testcase_driver.h +$(TEST_DRVS): testcase_driver@obj@ + + + diff --git a/erts/emulator/test/obsolete_SUITE_data/erl_threads.c b/erts/emulator/test/obsolete_SUITE_data/erl_threads.c new file mode 100644 index 0000000000..27a5163121 --- /dev/null +++ b/erts/emulator/test/obsolete_SUITE_data/erl_threads.c @@ -0,0 +1,302 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" + +#ifndef __WIN32__ + +#define NO_OF_THREADS 2 + +#include <unistd.h> +#include <errno.h> + +static int die; +static int cw_passed; +static int res_tf0; +static int res_tf1; +static erl_mutex_t mtx; +static erl_cond_t cnd; +static erl_thread_t tid[NO_OF_THREADS]; +static int need_join[NO_OF_THREADS]; + +typedef struct { + int n; +} thr_arg_t; + + +static void *tf0(void *vta) +{ + int r; + + if (((thr_arg_t *) vta)->n != 0) + goto fail; + + r = erts_mutex_lock(mtx); + if (r != 0) { + erts_mutex_unlock(mtx); + goto fail; + } + + r = erts_cond_wait(cnd, mtx); + if (r != 0 || die) { + erts_mutex_unlock(mtx); + goto fail; + } + + cw_passed++; + + r = erts_cond_wait(cnd, mtx); + if (r != 0 || die) { + erts_mutex_unlock(mtx); + goto fail; + } + + cw_passed++; + + r = erts_mutex_unlock(mtx); + if (r != 0) + goto fail; + + res_tf0 = 0; + + return (void *) &res_tf0; + + fail: + return NULL; +} + + +static void *tf1(void *vta) +{ + int r; + + if (((thr_arg_t *) vta)->n != 1) + goto fail; + + r = erts_mutex_lock(mtx); + if (r != 0) { + erts_mutex_unlock(mtx); + goto fail; + } + + r = erts_cond_wait(cnd, mtx); + if (r != 0 || die) { + erts_mutex_unlock(mtx); + goto fail; + } + + cw_passed++; + + r = erts_cond_wait(cnd, mtx); + if (r != 0 || die) { + erts_mutex_unlock(mtx); + goto fail; + } + + cw_passed++; + + r = erts_mutex_unlock(mtx); + if (r != 0) + goto fail; + + res_tf1 = 1; + + erts_thread_exit((void *) &res_tf1); + + res_tf1 = 4711; + + fail: + return NULL; +} + +#endif /* #ifndef __WIN32__ */ + +void +testcase_run(TestCaseState_t *tcs) +{ +#ifdef __WIN32__ + testcase_skipped(tcs, "Nothing to test; not supported on windows."); +#else + int i, r; + void *tres[NO_OF_THREADS]; + thr_arg_t ta[NO_OF_THREADS]; + erl_thread_t t1; + + die = 0; + cw_passed = 0; + + for (i = 0; i < NO_OF_THREADS; i++) + need_join[i] = 0; + + res_tf0 = 17; + res_tf1 = 17; + + cnd = mtx = NULL; + + /* Create mutex and cond */ + mtx = erts_mutex_create(); + ASSERT(tcs, mtx); + cnd = erts_cond_create(); + ASSERT(tcs, cnd); + + /* Create the threads */ + ta[0].n = 0; + r = erts_thread_create(&tid[0], tf0, (void *) &ta[0], 0); + ASSERT(tcs, r == 0); + need_join[0] = 1; + + ta[1].n = 1; + r = erts_thread_create(&tid[1], tf1, (void *) &ta[1], 0); + ASSERT(tcs, r == 0); + need_join[1] = 1; + + /* Make sure the threads waits on cond wait */ + sleep(1); + + r = erts_mutex_lock(mtx); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + ASSERT_CLNUP(tcs, cw_passed == 0, (void) erts_mutex_unlock(mtx)); + + + /* Let one thread pass one cond wait */ + r = erts_cond_signal(cnd); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + r = erts_mutex_unlock(mtx); + ASSERT(tcs, r == 0); + + sleep(1); + + r = erts_mutex_lock(mtx); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + ASSERT_CLNUP(tcs, cw_passed == 1, (void) erts_mutex_unlock(mtx)); + + + /* Let both threads pass one cond wait */ + r = erts_cond_broadcast(cnd); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + r = erts_mutex_unlock(mtx); + ASSERT(tcs, r == 0); + + sleep(1); + + r = erts_mutex_lock(mtx); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + ASSERT_CLNUP(tcs, cw_passed == 3, (void) erts_mutex_unlock(mtx)); + + + /* Let the thread that only have passed one cond wait pass the other one */ + r = erts_cond_signal(cnd); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + r = erts_mutex_unlock(mtx); + ASSERT(tcs, r == 0); + + sleep(1); + + r = erts_mutex_lock(mtx); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + ASSERT_CLNUP(tcs, cw_passed == 4, (void) erts_mutex_unlock(mtx)); + + /* Both threads should have passed both cond waits and exited; + join them and check returned values */ + + r = erts_thread_join(tid[0], &tres[0]); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + need_join[0] = 0; + + ASSERT_CLNUP(tcs, tres[0] == &res_tf0, (void) erts_mutex_unlock(mtx)); + ASSERT_CLNUP(tcs, res_tf0 == 0, (void) erts_mutex_unlock(mtx)); + + r = erts_thread_join(tid[1], &tres[1]); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + need_join[1] = 0; + + ASSERT_CLNUP(tcs, tres[1] == &res_tf1, (void) erts_mutex_unlock(mtx)); + ASSERT_CLNUP(tcs, res_tf1 == 1, (void) erts_mutex_unlock(mtx)); + + /* Test signaling when noone waits */ + + r = erts_cond_signal(cnd); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + /* Test broadcasting when noone waits */ + + r = erts_cond_broadcast(cnd); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + /* erts_cond_timedwait() not supported anymore */ + r = erts_cond_timedwait(cnd, mtx, 1000); + ASSERT_CLNUP(tcs, r != 0, (void) erts_mutex_unlock(mtx)); + ASSERT_CLNUP(tcs, + strcmp(erl_errno_id(r), "enotsup") == 0, + (void) erts_mutex_unlock(mtx)); + + r = erts_mutex_unlock(mtx); + ASSERT(tcs, r == 0); + + r = erts_mutex_destroy(mtx); + ASSERT(tcs, r == 0); + mtx = NULL; + + r = erts_cond_destroy(cnd); + ASSERT(tcs, r == 0); + cnd = NULL; + + /* ... */ + t1 = erts_thread_self(); + + if (cw_passed == 4711) { + /* We don't want to execute this just check that the + symbol/symbols is/are defined */ + erts_thread_kill(t1); + } + +#endif /* #ifndef __WIN32__ */ +} + +char * +testcase_name(void) +{ + return "erl_threads"; +} + +void +testcase_cleanup(TestCaseState_t *tcs) +{ + int i; + for (i = 0; i < NO_OF_THREADS; i++) { + if (need_join[i]) { + erts_mutex_lock(mtx); + die = 1; + erts_cond_broadcast(cnd); + erts_mutex_unlock(mtx); + erts_thread_join(tid[1], NULL); + } + } + if (mtx) + erts_mutex_destroy(mtx); + if (cnd) + erts_cond_destroy(cnd); +} + diff --git a/erts/emulator/test/obsolete_SUITE_data/testcase_driver.c b/erts/emulator/test/obsolete_SUITE_data/testcase_driver.c new file mode 100644 index 0000000000..99d5adb041 --- /dev/null +++ b/erts/emulator/test/obsolete_SUITE_data/testcase_driver.c @@ -0,0 +1,262 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <setjmp.h> +#include <string.h> + +#ifdef __WIN32__ +#undef HAVE_VSNPRINTF +#define HAVE_VSNPRINTF 1 +#define vsnprintf _vsnprintf +#endif + +#ifndef HAVE_VSNPRINTF +#define HAVE_VSNPRINTF 0 +#endif + +#define COMMENT_BUF_SZ 4096 + +#define TESTCASE_FAILED 0 +#define TESTCASE_SKIPPED 1 +#define TESTCASE_SUCCEEDED 2 + +typedef struct { + TestCaseState_t visible; + int port; + int result; + jmp_buf done_jmp_buf; + char *comment; + char comment_buf[COMMENT_BUF_SZ]; +} InternalTestCaseState_t; + +long testcase_drv_start(int port, char *command); +int testcase_drv_stop(long drv_data); +int testcase_drv_run(long drv_data, char *buf, int len); + +static DriverEntry testcase_drv_entry = { + NULL, + testcase_drv_start, + testcase_drv_stop, + testcase_drv_run +}; + + +int DRIVER_INIT(testcase_drv)(void *arg) +{ + testcase_drv_entry.driver_name = testcase_name(); + return (int) &testcase_drv_entry; +} + +long +testcase_drv_start(int port, char *command) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) + driver_alloc(sizeof(InternalTestCaseState_t)); + if (!itcs) { + return -1; + } + + itcs->visible.testcase_name = testcase_name(); + itcs->visible.extra = NULL; + itcs->port = port; + itcs->result = TESTCASE_FAILED; + itcs->comment = ""; + + return (long) itcs; +} + +int +testcase_drv_stop(long drv_data) +{ + testcase_cleanup((TestCaseState_t *) drv_data); + driver_free((void *) drv_data); + return 0; +} + +int +testcase_drv_run(long drv_data, char *buf, int len) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) drv_data; + DriverTermData result_atom; + DriverTermData msg[12]; + + itcs->visible.command = buf; + itcs->visible.command_len = len; + + if (setjmp(itcs->done_jmp_buf) == 0) { + testcase_run((TestCaseState_t *) itcs); + itcs->result = TESTCASE_SUCCEEDED; + } + + switch (itcs->result) { + case TESTCASE_SUCCEEDED: + result_atom = driver_mk_atom("succeeded"); + break; + case TESTCASE_SKIPPED: + result_atom = driver_mk_atom("skipped"); + break; + case TESTCASE_FAILED: + default: + result_atom = driver_mk_atom("failed"); + break; + } + + msg[0] = ERL_DRV_ATOM; + msg[1] = (DriverTermData) result_atom; + + msg[2] = ERL_DRV_PORT; + msg[3] = driver_mk_port(itcs->port); + + msg[4] = ERL_DRV_ATOM; + msg[5] = driver_mk_atom(itcs->visible.testcase_name); + + msg[6] = ERL_DRV_STRING; + msg[7] = (DriverTermData) itcs->comment; + msg[8] = (DriverTermData) strlen(itcs->comment); + + msg[9] = ERL_DRV_TUPLE; + msg[10] = (DriverTermData) 4; + + driver_output_term(itcs->port, msg, 11); + return 0; +} + +int +testcase_assertion_failed(TestCaseState_t *tcs, + char *file, int line, char *assertion) +{ + testcase_failed(tcs, "%s:%d: Assertion failed: \"%s\"", + file, line, assertion); + return 0; +} + +void +testcase_printf(TestCaseState_t *tcs, char *frmt, ...) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; + DriverTermData msg[12]; + va_list va; + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); +#else + vsprintf(itcs->comment_buf, frmt, va); +#endif + va_end(va); + + msg[0] = ERL_DRV_ATOM; + msg[1] = (DriverTermData) driver_mk_atom("print"); + + msg[2] = ERL_DRV_PORT; + msg[3] = driver_mk_port(itcs->port); + + msg[4] = ERL_DRV_ATOM; + msg[5] = driver_mk_atom(itcs->visible.testcase_name); + + msg[6] = ERL_DRV_STRING; + msg[7] = (DriverTermData) itcs->comment_buf; + msg[8] = (DriverTermData) strlen(itcs->comment_buf); + + msg[9] = ERL_DRV_TUPLE; + msg[10] = (DriverTermData) 4; + + driver_output_term(itcs->port, msg, 11); +} + + +void testcase_succeeded(TestCaseState_t *tcs, char *frmt, ...) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; + va_list va; + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); +#else + vsprintf(itcs->comment_buf, frmt, va); +#endif + va_end(va); + + itcs->result = TESTCASE_SUCCEEDED; + itcs->comment = itcs->comment_buf; + + longjmp(itcs->done_jmp_buf, 1); +} + +void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; + va_list va; + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); +#else + vsprintf(itcs->comment_buf, frmt, va); +#endif + va_end(va); + + itcs->result = TESTCASE_SKIPPED; + itcs->comment = itcs->comment_buf; + + longjmp(itcs->done_jmp_buf, 1); +} + +void testcase_failed(TestCaseState_t *tcs, char *frmt, ...) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; + char buf[10]; + size_t bufsz = sizeof(buf); + va_list va; + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); +#else + vsprintf(itcs->comment_buf, frmt, va); +#endif + va_end(va); + + itcs->result = TESTCASE_FAILED; + itcs->comment = itcs->comment_buf; + + if (erl_drv_getenv("ERL_ABORT_ON_FAILURE", buf, &bufsz) == 0 + && strcmp("true", buf) == 0) { + fprintf(stderr, "Testcase \"%s\" failed: %s\n", + itcs->visible.testcase_name, itcs->comment); + abort(); + } + + longjmp(itcs->done_jmp_buf, 1); +} + +void *testcase_alloc(size_t size) +{ + return driver_alloc(size); +} + +void *testcase_realloc(void *ptr, size_t size) +{ + return driver_realloc(ptr, size); +} + +void testcase_free(void *ptr) +{ + driver_free(ptr); +} diff --git a/erts/emulator/test/obsolete_SUITE_data/testcase_driver.h b/erts/emulator/test/obsolete_SUITE_data/testcase_driver.h new file mode 100644 index 0000000000..3d85ca6df0 --- /dev/null +++ b/erts/emulator/test/obsolete_SUITE_data/testcase_driver.h @@ -0,0 +1,57 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#ifndef TESTCASE_DRIVER_H__ +#define TESTCASE_DRIVER_H__ + +#include "obsolete/driver.h" +#include <stdlib.h> + +typedef struct { + char *testcase_name; + char *command; + int command_len; + void *extra; +} TestCaseState_t; + +#define ASSERT_CLNUP(TCS, B, CLN) \ +do { \ + if (!(B)) { \ + CLN; \ + testcase_assertion_failed((TCS), __FILE__, __LINE__, #B); \ + } \ +} while (0) + +#define ASSERT(TCS, B) ASSERT_CLNUP(TCS, B, (void) 0) + +void testcase_printf(TestCaseState_t *tcs, char *frmt, ...); +void testcase_succeeded(TestCaseState_t *tcs, char *frmt, ...); +void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...); +void testcase_failed(TestCaseState_t *tcs, char *frmt, ...); +int testcase_assertion_failed(TestCaseState_t *tcs, char *file, int line, + char *assertion); +void *testcase_alloc(size_t size); +void *testcase_realloc(void *ptr, size_t size); +void testcase_free(void *ptr); + + +char *testcase_name(void); +void testcase_run(TestCaseState_t *tcs); +void testcase_cleanup(TestCaseState_t *tcs); + +#endif diff --git a/erts/emulator/test/old_mod.erl b/erts/emulator/test/old_mod.erl new file mode 100644 index 0000000000..6c47ba6f8f --- /dev/null +++ b/erts/emulator/test/old_mod.erl @@ -0,0 +1,47 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(old_mod). +-compile(r10). + +-export([sort_on_old_node/1, sorter/3]). + +-include("test_server.hrl"). + +sorter(Receiver, Ref, List) -> + Receiver ! {Ref, lists:sort(List)}. + +sort_on_old_node(List) when is_list(List) -> + OldVersion = "r10", + ?line Pa = filename:dirname(code:which(?MODULE)), + ?line {X, Y, Z} = now(), + ?line NodeName = list_to_atom(OldVersion + ++ "_" + ++ integer_to_list(X) + ++ integer_to_list(Y) + ++ integer_to_list(Z)), + ?line {ok, Node} = ?t:start_node(NodeName, + peer, + [{args, " -pa " ++ Pa}, + {erl, [{release, OldVersion++"b_patched"}]}]), + ?line Ref = make_ref(), + ?line spawn_link(Node, ?MODULE, sorter, [self(), Ref, List]), + ?line SortedPids = receive {Ref, SP} -> SP end, + ?line true = ?t:stop_node(Node), + ?line SortedPids. diff --git a/erts/emulator/test/old_scheduler_SUITE.erl b/erts/emulator/test/old_scheduler_SUITE.erl new file mode 100644 index 0000000000..70348f64db --- /dev/null +++ b/erts/emulator/test/old_scheduler_SUITE.erl @@ -0,0 +1,394 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(old_scheduler_SUITE). + +-include("test_server.hrl"). + +-export([all/1, init_per_testcase/2, fin_per_testcase/2]). +-export([equal/1, many_low/1, few_low/1, max/1, high/1]). + +-define(default_timeout, ?t:minutes(11)). + +all(suite) -> + case catch erlang:system_info(modified_timing_level) of + Level when is_integer(Level) -> + {skipped, + "Modified timing (level " ++ integer_to_list(Level) + ++ ") is enabled. Testcases gets messed up by modfied " + "timing."}; + _ -> + [equal, many_low, few_low, max, high] + end. + +%%----------------------------------------------------------------------------------- +%% TEST SUITE DESCRIPTION +%% +%% The test case function spawns two controlling processes: Starter and Receiver. +%% Starter spawns a number of prio A and a number of prio B test processes. Each +%% test process loops for a number of times, sends a report to the Receiver, then +%% loops again. For each report, the Receiver increases a counter that corresponds +%% to the priority of the sender. After a certain amount of time, the Receiver +%% sends the collected data to the main test process and waits for the test case +%% to terminate. From this data, it's possible to calculate the average run time +%% relationship between the prio A and B test processes. +%% +%% Note that in order to be able to run tests with high or max prio test processes, +%% the main test process and the Receiver needs to run at max prio, or they will +%% be starved by the test processes. The controlling processes must not wait for +%% messages from a normal (or low) prio process while max or high prio test processes +%% are running (which happens e.g. if an io function is called). +%%----------------------------------------------------------------------------------- + +init_per_testcase(_Case, Config) -> + ?line Dog = test_server:timetrap(?default_timeout), + %% main test process needs max prio + ?line Prio = process_flag(priority, max), + ?line MS = erlang:system_flag(multi_scheduling, block), + [{prio,Prio},{watchdog,Dog},{multi_scheduling, MS}|Config]. + +fin_per_testcase(_Case, Config) -> + erlang:system_flag(multi_scheduling, unblock), + Dog=?config(watchdog, Config), + Prio=?config(prio, Config), + process_flag(priority, Prio), + test_server:timetrap_cancel(Dog), + ok. + +ok(Config) when is_list(Config) -> + case ?config(multi_scheduling, Config) of + blocked -> + {comment, + "Multi-scheduling blocked during test. This testcase was not " + "written to work with multiple schedulers."}; + _ -> ok + end. + +%% Run equal number of low and normal prio processes. + +equal(suite) -> []; +equal(doc) -> []; +equal(Config) when is_list(Config) -> + ?line Self = self(), + + %% specify number of test processes to run + Normal = {normal,500}, + Low = {low,500}, + + %% specify time of test (in seconds) + Time = 30, + + %% start controllers + ?line Receiver = + spawn(fun() -> receiver(now(), Time, Self, Normal, Low) end), + ?line Starter = + spawn(fun() -> starter(Normal, Low, Receiver) end), + + %% receive test data from Receiver + ?line {NRs,NAvg,LRs,LAvg,Ratio} = + receive + {Receiver,Res} -> Res + end, + + %% stop controllers and test processes + ?line exit(Starter, kill), + ?line exit(Receiver, kill), + + io:format("Reports: ~w normal (~w/proc), ~w low (~w/proc). Ratio: ~w~n", + [NRs,NAvg,LRs,LAvg,Ratio]), + + %% runtime ratio between normal and low should be ~8 + if Ratio < 7.5 ; Ratio > 8.5 -> + ?t:fail({bad_ratio,Ratio}); + true -> + ok(Config) + end. + + +%% Run many low and few normal prio processes. + +many_low(suite) -> []; +many_low(doc) -> []; +many_low(Config) when is_list(Config) -> + ?line Self = self(), + Normal = {normal,1}, + Low = {low,1000}, + + %% specify time of test (in seconds) + Time = 30, + + ?line Receiver = + spawn(fun() -> receiver(now(), Time, Self, Normal, Low) end), + ?line Starter = + spawn(fun() -> starter(Normal, Low, Receiver) end), + ?line {NRs,NAvg,LRs,LAvg,Ratio} = + receive + {Receiver,Res} -> Res + end, + ?line exit(Starter, kill), + ?line exit(Receiver, kill), + io:format("Reports: ~w normal (~w/proc), ~w low (~w/proc). Ratio: ~w~n", + [NRs,NAvg,LRs,LAvg,Ratio]), + if Ratio < 7.5 ; Ratio > 8.5 -> + ?t:fail({bad_ratio,Ratio}); + true -> + ok(Config) + end. + + +%% Run few low and many normal prio processes. + +few_low(suite) -> []; +few_low(doc) -> []; +few_low(Config) when is_list(Config) -> + ?line Self = self(), + Normal = {normal,1000}, + Low = {low,1}, + + %% specify time of test (in seconds) + Time = 30, + + ?line Receiver = + spawn(fun() -> receiver(now(), Time, Self, Normal, Low) end), + ?line Starter = + spawn(fun() -> starter(Normal, Low, Receiver) end), + ?line {NRs,NAvg,LRs,LAvg,Ratio} = + receive + {Receiver,Res} -> Res + end, + ?line exit(Starter, kill), + ?line exit(Receiver, kill), + io:format("Reports: ~w normal (~w/proc), ~w low (~w/proc). Ratio: ~w~n", + [NRs,NAvg,LRs,LAvg,Ratio]), + if Ratio < 7.0 ; Ratio > 8.5 -> + ?t:fail({bad_ratio,Ratio}); + true -> + ok(Config) + end. + + +%% Run max prio processes and verify they get at least as much +%% runtime as high, normal and low. + +max(suite) -> []; +max(doc) -> []; +max(Config) when is_list(Config) -> + max = process_flag(priority, max), % should already be max (init_per_tc) + ?line Self = self(), + Max = {max,2}, + High = {high,2}, + Normal = {normal,100}, + Low = {low,100}, + + %% specify time of test (in seconds) + Time = 30, + + ?line Receiver1 = + spawn(fun() -> receiver(now(), Time, Self, Max, High) end), + ?line Starter1 = + spawn(fun() -> starter(Max, High, Receiver1) end), + ?line {M1Rs,M1Avg,HRs,HAvg,Ratio1} = + receive + {Receiver1,Res1} -> Res1 + end, + ?line exit(Starter1, kill), + ?line exit(Receiver1, kill), + io:format("Reports: ~w max (~w/proc), ~w high (~w/proc). Ratio: ~w~n", + [M1Rs,M1Avg,HRs,HAvg,Ratio1]), + if Ratio1 < 1.0 -> + ?t:fail({bad_ratio,Ratio1}); + true -> + ok(Config) + end, + + ?line Receiver2 = + spawn(fun() -> receiver(now(), Time, Self, Max, Normal) end), + ?line Starter2 = + spawn(fun() -> starter(Max, Normal, Receiver2) end), + ?line {M2Rs,M2Avg,NRs,NAvg,Ratio2} = + receive + {Receiver2,Res2} -> Res2 + end, + ?line exit(Starter2, kill), + ?line exit(Receiver2, kill), + io:format("Reports: ~w max (~w/proc), ~w normal (~w/proc). Ratio: ~w~n", + [M2Rs,M2Avg,NRs,NAvg,Ratio2]), + if Ratio2 < 1.0 -> + ?t:fail({bad_ratio,Ratio2}); + true -> + ok + end, + + ?line Receiver3 = + spawn(fun() -> receiver(now(), Time, Self, Max, Low) end), + ?line Starter3 = + spawn(fun() -> starter(Max, Low, Receiver3) end), + ?line {M3Rs,M3Avg,LRs,LAvg,Ratio3} = + receive + {Receiver3,Res3} -> Res3 + end, + ?line exit(Starter3, kill), + ?line exit(Receiver3, kill), + io:format("Reports: ~w max (~w/proc), ~w low (~w/proc). Ratio: ~w~n", + [M3Rs,M3Avg,LRs,LAvg,Ratio3]), + if Ratio3 < 1.0 -> + ?t:fail({bad_ratio,Ratio3}); + true -> + ok(Config) + end. + + +%% Run high prio processes and verify they get at least as much +%% runtime as normal and low. + +high(suite) -> []; +high(doc) -> []; +high(Config) when is_list(Config) -> + max = process_flag(priority, max), % should already be max (init_per_tc) + ?line Self = self(), + High = {high,2}, + Normal = {normal,100}, + Low = {low,100}, + + %% specify time of test (in seconds) + Time = 30, + + ?line Receiver1 = + spawn(fun() -> receiver(now(), Time, Self, High, Normal) end), + ?line Starter1 = + spawn(fun() -> starter(High, Normal, Receiver1) end), + ?line {H1Rs,H1Avg,NRs,NAvg,Ratio1} = + receive + {Receiver1,Res1} -> Res1 + end, + ?line exit(Starter1, kill), + ?line exit(Receiver1, kill), + io:format("Reports: ~w high (~w/proc), ~w normal (~w/proc). Ratio: ~w~n", + [H1Rs,H1Avg,NRs,NAvg,Ratio1]), + if Ratio1 < 1.0 -> + ?t:fail({bad_ratio,Ratio1}); + true -> + ok + end, + + ?line Receiver2 = + spawn(fun() -> receiver(now(), Time, Self, High, Low) end), + ?line Starter2 = + spawn(fun() -> starter(High, Low, Receiver2) end), + ?line {H2Rs,H2Avg,LRs,LAvg,Ratio2} = + receive + {Receiver2,Res2} -> Res2 + end, + ?line exit(Starter2, kill), + ?line exit(Receiver2, kill), + io:format("Reports: ~w high (~w/proc), ~w low (~w/proc). Ratio: ~w~n", + [H2Rs,H2Avg,LRs,LAvg,Ratio2]), + if Ratio2 < 1.0 -> + ?t:fail({bad_ratio,Ratio2}); + true -> + ok(Config) + end. + + +%%----------------------------------------------------------------------------------- +%% Controller processes and help functions +%%----------------------------------------------------------------------------------- + +receiver(T0, TimeSec, Main, {P1,P1N}, {P2,P2N}) -> + %% prio should be max so that mailbox doesn't overflow + process_flag(priority, max), + receiver(T0, TimeSec*1000, Main, P1,P1N,0, P2,P2N,0, 100000). + +%% uncomment lines below to get life sign (debug) +receiver(T0, Time, Main, P1,P1N,P1Rs, P2,P2N,P2Rs, 0) -> +% T = elapsed_ms(T0, now()), +% erlang:display({round(T/1000),P1Rs,P2Rs}), + receiver(T0, Time, Main, P1,P1N,P1Rs, P2,P2N,P2Rs, 100000); + +receiver(T0, Time, Main, P1,P1N,P1Rs, P2,P2N,P2Rs, C) -> + Remain = Time - elapsed_ms(T0, now()), % test time remaining + Remain1 = if Remain < 0 -> + 0; + true -> + Remain + end, + {P1Rs1,P2Rs1} = + receive + {_Pid,P1} -> % report from a P1 process + {P1Rs+1,P2Rs}; + {_Pid,P2} -> % report from a P2 process + {P1Rs,P2Rs+1} + after Remain1 -> + {P1Rs,P2Rs} + end, + if Remain > 0 -> % keep going + receiver(T0, Time, Main, P1,P1N,P1Rs1, P2,P2N,P2Rs1, C-1); + true -> % finish + %% calculate results and send to main test process + P1Avg = P1Rs1/P1N, + P2Avg = P2Rs1/P2N, + Ratio = if P2Avg < 1.0 -> P1Avg; + true -> P1Avg/P2Avg + end, + Main ! {self(),{P1Rs1,round(P1Avg),P2Rs1,round(P2Avg),Ratio}}, + flush_loop() + end. + +starter({P1,P1N}, {P2,P2N}, Receiver) -> + %% start N1 processes with prio P1 + start_p(P1, P1N, Receiver), + %% start N2 processes with prio P2 + start_p(P2, P2N, Receiver), + erlang:display({started,P1N+P2N}), + flush_loop(). + +start_p(_, 0, _) -> + ok; +start_p(Prio, N, Receiver) -> + spawn_link(fun() -> p(Prio, Receiver) end), + start_p(Prio, N-1, Receiver). + +p(Prio, Receiver) -> + %% set process priority + process_flag(priority, Prio), + p_loop(0, Prio, Receiver). + +p_loop(100, Prio, Receiver) -> + receive after 0 -> ok end, + %% if Receiver gone, we're done + case is_process_alive(Receiver) of + false -> exit(bye); + true -> ok + end, + %% send report + Receiver ! {self(),Prio}, + p_loop(0, Prio, Receiver); + +p_loop(N, Prio, Receiver) -> + p_loop(N+1, Prio, Receiver). + + +flush_loop() -> + receive _ -> + ok + end, + flush_loop(). + +elapsed_ms({_MS0,S0,MuS0},{_MS1,S1,MuS1}) -> + round(((S1-S0)*1000)+((MuS1-MuS0)/1000)). diff --git a/erts/emulator/test/op_SUITE.erl b/erts/emulator/test/op_SUITE.erl new file mode 100644 index 0000000000..55d8d9ab0f --- /dev/null +++ b/erts/emulator/test/op_SUITE.erl @@ -0,0 +1,368 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(op_SUITE). + +-include("test_server.hrl"). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + bsl_bsr/1,logical/1,t_not/1,relop_simple/1,relop/1,complex_relop/1]). + +-export([]). +-import(lists, [foldl/3,flatmap/2]). + +all(suite) -> + [bsl_bsr,logical,t_not,relop_simple,relop,complex_relop]. + +init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> + Dog=?t:timetrap(?t:minutes(3)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +%% Test the bsl and bsr operators. +bsl_bsr(Config) when is_list(Config) -> + Vs = [unvalue(V) || V <- [-16#8000009-2,-1,0,1,2,73,16#8000000,bad,[]]], + Cases = [{Op,X,Y} || Op <- ['bsr','bsl'], X <- Vs, Y <- Vs], + ?line run_test_module(Cases, false), + {comment,integer_to_list(length(Cases)) ++ " cases"}. + +logical(doc) -> "Test the logical operators and internal BIFs."; +logical(Config) when is_list(Config) -> + Vs0 = [true,false,bad], + Vs = [unvalue(V) || V <- Vs0], + Cases = [{Op,X,Y} || Op <- ['and','or','xor'], X <- Vs, Y <- Vs], + ?line run_test_module(Cases, false), + {comment,integer_to_list(length(Cases)) ++ " cases"}. + +t_not(doc) -> "Test the not operator and internal BIFs."; +t_not(Config) when is_list(Config) -> + ?line Cases = [{'not',unvalue(V)} || V <- [true,false,42,bad]], + ?line run_test_module(Cases, false), + {comment,integer_to_list(length(Cases)) ++ " cases"}. + +relop_simple(doc) -> "Test that simlpe relations between relation operators hold."; +relop_simple(Config) when is_list(Config) -> + Big1 = 19738924729729787487784874, + Big2 = 38374938373887374983978484, + F1 = float(Big1), + F2 = float(Big2), + T1 = erlang:make_tuple(3,87), + T2 = erlang:make_tuple(3,87), + Terms = [-F2,Big2,-F1,-Big1,-33,-33.0,0,0.0,42,42.0,Big1,F1,Big2,F2,a,b, + {T1,a},{T2,b},[T1,Big1],[T2,Big2]], + + ?line Combos = [{V1,V2} || V1 <- Terms, V2 <- Terms], + + lists:foreach(fun({A,B}) -> relop_simple_do(A,B) end, + Combos), + + repeat(fun() -> Size = random:uniform(100), + Rnd1 = make_rand_term(Size), + {Rnd2,0} = clone_and_mutate(Rnd1, random:uniform(Size)), + relop_simple_do(Rnd1,Rnd2) + end, + 1000), + ok. + +relop_simple_do(V1,V2) -> + %%io:format("compare ~p\n and ~p\n",[V1,V2]), + + L = V1 < V2, + ?line L = not (V1 >= V2), + ?line L = V2 > V1, + ?line L = not (V2 =< V1), + + G = V1 > V2, + ?line G = not (V1 =< V2), + ?line G = V2 < V1, + ?line G = not (V2 >= V1), + + ID = V1 =:= V2, + ?line ID = V2 =:= V1, + ?line ID = not (V1 =/= V2), + ?line ID = not (V2 =/= V1), + + EQ = V1 == V2, + ?line EQ = V2 == V1, + ?line EQ = not (V1 /= V2), + ?line EQ = not (V2 /= V1), + + ?line case {L, EQ, ID, G, cmp_emu(V1,V2)} of + { true, false, false, false, -1} -> ok; + {false, true, false, false, 0} -> ok; + {false, true, true, false, 0} -> ok; + {false, false, false, true, +1} -> ok + end. + +%% Emulate internal "cmp" +cmp_emu(A,B) when is_tuple(A), is_tuple(B) -> + SA = size(A), + SB = size(B), + if SA =:= SB -> cmp_emu(tuple_to_list(A),tuple_to_list(B)); + SA > SB -> +1; + SA < SB -> -1 + end; +cmp_emu([A|TA],[B|TB]) -> + case cmp_emu(A,B) of + 0 -> cmp_emu(TA,TB); + CMP -> CMP + end; +cmp_emu(A,B) -> + %% We cheat and use real "cmp" for the primitive types. + if A < B -> -1; + A > B -> +1; + true -> 0 + end. + +make_rand_term(1) -> + make_rand_term_single(); +make_rand_term(Arity) -> + case random:uniform(3) of + 1 -> + make_rand_list(Arity); + 2 -> + list_to_tuple(make_rand_list(Arity)); + 3 -> + {Car,Rest} = make_rand_term_rand_size(Arity), + [Car|make_rand_term(Rest)] + end. + +make_rand_term_single() -> + Range = 1 bsl random:uniform(200), + case random:uniform(12) of + 1 -> random; + 2 -> uniform; + 3 -> random:uniform(Range) - (Range div 2); + 4 -> Range * (random:uniform() - 0.5); + 5 -> 0; + 6 -> 0.0; + 7 -> make_ref(); + 8 -> self(); + 9 -> term_to_binary(random:uniform(Range)); + 10 -> fun(X) -> X*Range end; + 11 -> fun(X) -> X/Range end; + 12 -> [] + end. + +make_rand_term_rand_size(1) -> + {make_rand_term(1), 0}; +make_rand_term_rand_size(MaxArity) -> + Arity = random:uniform(MaxArity-1), + {make_rand_term(Arity), MaxArity-Arity}. + +make_rand_list(0) -> []; +make_rand_list(Arity) -> + {Term, Rest} = make_rand_term_rand_size(Arity), + [Term | make_rand_list(Rest)]. + + +clone_and_mutate(Term, 0) -> + {clone(Term), 0}; +clone_and_mutate(_Term, 1) -> + {Mutation, _} = make_rand_term_rand_size(10), % MUTATE! + {Mutation, 0}; +clone_and_mutate(Term, Cnt) when is_tuple(Term) -> + {Clone,NewCnt} = clone_and_mutate(tuple_to_list(Term),Cnt), + {my_list_to_tuple(Clone), NewCnt}; +clone_and_mutate([Term|Tail], Cnt) -> + {Car,Cnt1} = clone_and_mutate(Term,Cnt), + {Cdr,Cnt2} = clone_and_mutate(Tail,Cnt1), + {[Car | Cdr], Cnt2}; +clone_and_mutate(Term, Cnt) -> + {clone(Term), Cnt-1}. + +clone(Term) -> + binary_to_term(term_to_binary(Term)). + +my_list_to_tuple(List) -> + try list_to_tuple(List) + catch + error:badarg -> + %%io:format("my_list_to_tuple got badarg exception.\n"), + list_to_tuple(purify_list(List)) + end. + +purify_list(List) -> + lists:reverse(purify_list(List, [])). +purify_list([], Acc) -> Acc; +purify_list([H|T], Acc) -> purify_list(T, [H|Acc]); +purify_list(Other, Acc) -> [Other|Acc]. + + +relop(doc) -> "Test the relational operators and internal BIFs on literals."; +relop(Config) when is_list(Config) -> + Big1 = -38374938373887374983978484, + Big2 = 19738924729729787487784874, + F1 = float(Big1), + F2 = float(Big2), + Vs0 = [a,b,-33,-33.0,0,0.0,42,42.0,Big1,Big2,F1,F2], + ?line Vs = [unvalue(V) || V <- Vs0], + Ops = ['==', '/=', '=:=', '=/=', '<', '=<', '>', '>='], + ?line binop(Ops, Vs). + +complex_relop(doc) -> + "Test the relational operators and internal BIFs on lists and tuples."; +complex_relop(Config) when is_list(Config) -> + Big = 99678557475484872464269855544643333, + Float = float(Big), + Vs0 = [an_atom,42.0,42,Big,Float], + Vs = flatmap(fun(X) -> [unvalue({X}),unvalue([X])] end, Vs0), + Ops = ['==', '/=', '=:=', '=/=', '<', '=<', '>', '>='], + ?line binop(Ops, Vs). + +binop(Ops, Vs) -> + Run = fun(Op, N) -> ?line Cases = [{Op,V1,V2} || V1 <- Vs, V2 <- Vs], + ?line run_test_module(Cases, true), + N + length(Cases) end, + ?line NumCases = foldl(Run, 0, Ops), + {comment,integer_to_list(NumCases) ++ " cases"}. + +run_test_module(Cases, GuardsOk) -> + ?line Es = [expr(C) || C <- Cases], + ?line Ok = unvalue(ok), + ?line Gts = case GuardsOk of + true -> + Ges = [guard_expr(C) || C <- Cases], + ?line lists:foldr(fun guard_test/2, [Ok], Ges); + false -> + [Ok] + end, + ?line Fun1 = make_function(guard_tests, Gts), + ?line Bts = lists:foldr(fun body_test/2, [Ok], Es), + ?line Fun2 = make_function(body_tests, Bts), + ?line Bbts = lists:foldr(fun internal_bif/2, [Ok], Es), + ?line Fun3 = make_function(bif_tests, Bbts), + ?line Id = {function,1,id,1,[{clause,1,[{var,1,'I'}],[],[{var,1,'I'}]}]}, + ?line Module = make_module(op_tests, [Fun1,Fun2,Fun3,Id]), + ?line lists:foreach(fun(F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Module), + + %% Compile, load, and run the generated module. + + Native = case ?t:is_native(?MODULE) of + true -> [native]; + false -> [] + end, + ?line {ok,Mod,Code1} = compile:forms(Module, [time|Native]), + ?line code:delete(Mod), + ?line code:purge(Mod), + ?line {module,Mod} = code:load_binary(Mod, Mod, Code1), + ?line run_function(Mod, guard_tests), + ?line run_function(Mod, body_tests), + ?line run_function(Mod, bif_tests), + + ?line true = code:delete(Mod), + ?line code:purge(Mod), + + ok. + +expr({Op,X}) -> + E = {op,1,Op,{call,1,{atom,1,id},[X]}}, + Res = eval([{op,1,Op,X}]), + {E,{Op,X},Res}; +expr({Op,X,Y}) -> + E = {op,1,Op,{call,1,{atom,1,id},[X]},Y}, + Res = eval([{op,1,Op,X,Y}]), + {E,{Op,value(X),value(Y)},Res}. + +guard_expr({Op,X}) -> + E = {op,1,Op,X}, + Res = eval([E]), + {E,{Op,X},Res}; +guard_expr({Op,X,Y}) -> + E = {op,1,Op,X,Y}, + Res = eval([E]), + {E,{Op,value(X),value(Y)},Res}. + +run_function(Mod, Name) -> + case catch Mod:Name() of + {'EXIT',Reason} -> + io:format("~p", [get(last)]), + ?t:fail({'EXIT',Reason}); + _Other -> + ok + end. + +guard_test({E,Expr,Res}, Tail) -> + True = unvalue(true), + [save_term(Expr), + {match,1,unvalue(Res), + {'if',1,[{clause,1,[],[[E]],[True]}, + {clause,1,[],[[True]],[unvalue(false)]}]}}|Tail]. + +body_test({E,Expr,{'EXIT',_}}, Tail) -> + [save_term(Expr), + {match,1,{tuple,1,[unvalue('EXIT'), {var,1,'_'}]}, + {'catch',1,E}}|Tail]; +body_test({E,Expr,Res}, Tail) -> + [save_term(Expr), + {match,1,unvalue(Res),E}|Tail]. + +internal_bif({{op,_,Op,X},Expr,Res}, Tail) -> + internal_bif(Op, [X], Expr, Res, Tail); +internal_bif({{op,_,Op,X,Y},Expr,Res}, Tail) -> + internal_bif(Op, [X,Y], Expr, Res, Tail). + +internal_bif(Op, Args, Expr, {'EXIT',_}, Tail) -> + [save_term(Expr), + {match,1,{tuple,1,[unvalue('EXIT'), {var,1,'_'}]}, + {'catch',1,{call,1,{remote,1,{atom,1,erlang},unvalue(Op)},Args}}}|Tail]; +internal_bif(Op, Args, Expr, Res, Tail) -> + [save_term(Expr), + {match,1,unvalue(Res), + {call,1,{remote,1,{atom,1,erlang},unvalue(Op)},Args}}|Tail]. + +save_term(Term) -> + {call,1, + {atom,1,put}, + [{atom,1,last},unvalue(Term)]}. + +make_module(Name, Funcs) -> + [{attribute,1,module,Name}, + {attribute,0,compile,export_all}, + {attribute,0,compile,[{hipe,[{regalloc,linear_scan}]}]} | + Funcs ++ [{eof,0}]]. + +make_function(Name, Body) -> + {function,1,Name,0,[{clause,1,[],[],Body}]}. + +eval(E) -> + ?line case catch erl_eval:exprs(E, []) of + {'EXIT',Reason} -> {'EXIT',Reason}; + {value,Val,_Bs} -> Val + end. + +unvalue(V) -> erl_parse:abstract(V). + +value({nil,_}) -> []; +value({integer,_,X}) -> X; +value({string,_,X}) -> X; +value({float,_,X}) -> X; +value({atom,_,X}) -> X; +value({tuple,_,Es}) -> + list_to_tuple(lists:map(fun(X) -> value(X) end, Es)); +value({cons,_,H,T}) -> + [value(H) | value(T)]. + +repeat(_, 0) -> ok; +repeat(Fun, N) -> + Fun(), + repeat(Fun, N-1). diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl new file mode 100644 index 0000000000..9a09d20eab --- /dev/null +++ b/erts/emulator/test/port_SUITE.erl @@ -0,0 +1,2288 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(port_SUITE). + +%%% +%%% Author: Bjorn Gustavsson; iter_max_ports contributed by Peter Hogfeldt. +%%% + +%% +%% There are a lot of things to test with open_port(Name, Settings). +%% +%% Name can be +%% +%% {spawn, Command} +%% which according to The Book and the manual page starts an +%% external program. That is not true. It might very well be +%% a linked-in program (the notion of 'linked-in driver' is +%% silly, since any driver is 'linked-in'). +%% [Spawn of external program is tested.] +%% +%% Atom +%% Read all contents of Atom, or write to it. +%% +%% {fd, In, Out} +%% Open file descriptors In and Out. [Not tested] +%% +%% PortSettings can be +%% +%% {packet, N} +%% N is 1, 2 or 4. +%% +%% stream (default) +%% Without packet length. +%% +%% use_stdio (default for spawned ports) +%% The spawned process use file descriptors 0 and 1 for I/O. +%% +%% nouse_stdio [Not tested] +%% Use filedescriptors 3 and 4. This option is probably only +%% meaningful on Unix. +%% +%% in (default for Atom) +%% Input only (from Erlang's point of view). +%% +%% out +%% Output only (from Erlang's point of view). +%% +%% binary +%% The port is a binary port, i.e. messages received and sent +%% to a port are binaries. +%% +%% eof +%% Port is not closed on eof and will not send an exit signal, +%% instead it will send a {Port, eof} to the controlling process +%% (output can still be sent to the port (??)). +%% + + +-export([all/1, init_per_testcase/2, fin_per_testcase/2, + init_per_suite/1, end_per_suite/1, + stream/1, stream_small/1, stream_big/1, + basic_ping/1, slow_writes/1, bad_packet/1, bad_port_messages/1, + multiple_packets/1, mul_basic/1, mul_slow_writes/1, + dying_port/1, port_program_with_path/1, + open_input_file_port/1, open_output_file_port/1, + iter_max_ports/1, eof/1, input_only/1, output_only/1, + name1/1, + t_binary/1, options/1, parallell/1, t_exit/1, + env/1, bad_env/1, cd/1, exit_status/1, + tps/1, tps_16_bytes/1, tps_1K/1, line/1, stderr_to_stdout/1, + otp_3906/1, otp_4389/1, win_massive/1, win_massive_client/1, + mix_up_ports/1, otp_5112/1, otp_5119/1, otp_6224/1, + exit_status_multi_scheduling_block/1, ports/1, + spawn_driver/1,spawn_executable/1]). + +-export([]). + +%% Internal exports. +-export([tps/3]). +-export([otp_3906_forker/5, otp_3906_start_forker_starter/4]). +-export([env_slave_main/1]). + +-include("test_server.hrl"). +-include_lib("kernel/include/file.hrl"). + +all(suite) -> + [ + otp_6224, stream, basic_ping, slow_writes, bad_packet, + bad_port_messages, options, multiple_packets, parallell, + dying_port, port_program_with_path, + open_input_file_port, open_output_file_port, + name1, + env, bad_env, cd, exit_status, + iter_max_ports, t_exit, tps, line, stderr_to_stdout, + otp_3906, otp_4389, win_massive, mix_up_ports, + otp_5112, otp_5119, + exit_status_multi_scheduling_block, + ports, spawn_driver, spawn_executable + ]. + +-define(DEFAULT_TIMEOUT, ?t:minutes(5)). + +init_per_testcase(Case, Config) -> + [{testcase, Case} |Config]. + +fin_per_testcase(_Case, _Config) -> + ok. + +init_per_suite(Config) when is_list(Config) -> + ignore_cores:init(Config). + +end_per_suite(Config) when is_list(Config) -> + ignore_cores:fini(Config). + + +-define(WIN_MASSIVE_PORT, 50000). + +%% Tests that you can open a massive amount of ports (sockets) +%% on a Windows machine given the correct environment. +win_massive(Config) when is_list(Config) -> + case os:type() of + {win32,_} -> + do_win_massive(); + _ -> + {skip,"Only on Windows."} + end. + +do_win_massive() -> + ?line Dog = test_server:timetrap(test_server:seconds(360)), + ?line SuiteDir = filename:dirname(code:which(?MODULE)), + ?line Env = " -env ERL_MAX_PORTS 8192", + ?line {ok, Node} = + test_server:start_node(win_massive, + slave, + [{args, " -pa " ++ SuiteDir ++ Env}]), + ?line ok = rpc:call(Node,?MODULE,win_massive_client,[3000]), + ?line test_server:stop_node(Node), + ?line test_server:timetrap_cancel(Dog), + ok. + +win_massive_client(N) -> + {ok,P}=gen_tcp:listen(?WIN_MASSIVE_PORT,[{reuseaddr,true}]), + L = win_massive_loop(P,N), + Len = length(L), + lists:foreach(fun(E) -> + gen_tcp:close(E) + end, + L), + case Len div 2 of + N -> + ok; + _Else -> + {too_few, Len} + end. + +win_massive_loop(_,0) -> + []; +win_massive_loop(P,N) -> + case (catch gen_tcp:connect("localhost",?WIN_MASSIVE_PORT,[])) of + {ok,A} -> + case (catch gen_tcp:accept(P)) of + {ok,B} -> + %erlang:display(N), + [A,B|win_massive_loop(P,N-1)]; + _Else -> + [A] + end; + _Else0 -> + [] + end. + + + + +stream(suite) -> [stream_small, stream_big]. + +%% Test that we can send a stream of bytes and get it back. +%% We will send only a small amount of data, to avoid deadlock. + +stream_small(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line stream_ping(Config, 512, "", []), + ?line stream_ping(Config, 1777, "", []), + ?line stream_ping(Config, 1777, "-s512", []), + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Send big amounts of data (much bigger than the buffer size in port test). +%% This will deadlock the emulator if the spawn driver haven't proper +%% non-blocking reads and writes. + +stream_big(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(180)), + case os:type() of + vxworks -> + %% Don't stress VxWorks too much + ?line stream_ping(Config, 43755, "", []), + ?line stream_ping(Config, 51255, "", []), + ?line stream_ping(Config, 52345, " -s40000", []); + _ -> + ?line stream_ping(Config, 43755, "", []), + ?line stream_ping(Config, 100000, "", []), + ?line stream_ping(Config, 77777, " -s40000", []) + end, + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Sends packet with header size of 1, 2, and 4, with packets of various +%% sizes. + +basic_ping(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(120)), + ?line ping(Config, sizes(1), 1, "", []), + ?line ping(Config, sizes(2), 2, "", []), + ?line ping(Config, sizes(4), 4, "", []), + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Let the port program insert delays between characters sent back to +%% Erlang, to test that the Erlang emulator can handle a packet coming in +%% small chunks rather than all at once. + +slow_writes(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(20)), + ?line ping(Config, [8], 4, "-s1", []), + ?line ping(Config, [10], 2, "-s2", []), + ?line test_server:timetrap_cancel(Dog), + ok. + +bad_packet(doc) -> + ["Test that we get {'EXIT', Port, einval} if we try to send a bigger " + "packet than the packet header allows."]; +bad_packet(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line PortTest = port_test(Config), + ?line process_flag(trap_exit, true), + + ?line bad_packet(PortTest, 1, 256), + ?line bad_packet(PortTest, 1, 257), + ?line bad_packet(PortTest, 2, 65536), + ?line bad_packet(PortTest, 2, 65537), + + ?line test_server:timetrap_cancel(Dog), + ok. + +bad_packet(PortTest, HeaderSize, PacketSize) -> + %% Intentionally no ?line macros. + P = open_port({spawn, PortTest}, [{packet, HeaderSize}]), + P ! {self(), {command, make_zero_packet(PacketSize)}}, + receive + {'EXIT', P, einval} -> ok; + Other -> test_server:fail({unexpected_message, Other}) + end. + +make_zero_packet(0) -> []; +make_zero_packet(N) when N rem 2 == 0 -> + P = make_zero_packet(N div 2), + [P|P]; +make_zero_packet(N) -> + P = make_zero_packet(N div 2), + [0, P|P]. + +%% Test sending bad messages to a port. +bad_port_messages(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line PortTest = port_test(Config), + ?line process_flag(trap_exit, true), + + ?line bad_message(PortTest, {a,b}), + ?line bad_message(PortTest, {a}), + ?line bad_message(PortTest, {self(),{command,bad_command}}), + ?line bad_message(PortTest, {self(),{connect,no_pid}}), + + ?line test_server:timetrap_cancel(Dog), + ok. + +bad_message(PortTest, Message) -> + P = open_port({spawn,PortTest}, []), + P ! Message, + receive + {'EXIT',P,badsig} -> ok; + Other -> test_server:fail({unexpected_message, Other}) + end. + +%% Tests various options (stream and {packet, Number} are implicitly +%% tested in other test cases). + +options(suite) -> [t_binary, eof, input_only, output_only]. + +%% Tests the 'binary' option for a port. + +t_binary(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(300)), + + %% Packet mode. + ?line ping(Config, sizes(1), 1, "", [binary]), + ?line ping(Config, sizes(2), 2, "", [binary]), + ?line ping(Config, sizes(4), 4, "", [binary]), + + %% Stream mode. + case os:type() of + vxworks -> + %% don't stress VxWorks too much + ?line stream_ping(Config, 435, "", [binary]), + ?line stream_ping(Config, 43755, "", [binary]), + ?line stream_ping(Config, 50000, "", [binary]); + _ -> + ?line stream_ping(Config, 435, "", [binary]), + ?line stream_ping(Config, 43755, "", [binary]), + ?line stream_ping(Config, 100000, "", [binary]) + end, + + ?line test_server:timetrap_cancel(Dog), + ok. + +name1(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(100)), + ?line PortTest = port_test(Config), + ?line Command = lists:concat([PortTest, " "]), + ?line P = open_port({spawn, Command}, []), + ?line register(myport, P), + ?line P = whereis(myport), + Text = "hej", + ?line myport ! {self(), {command, Text}}, + ?line receive + {P, {data, Text}} -> + ok + end, + ?line myport ! {self(), close}, + ?line receive + {P, closed} -> ok + end, + ?line undefined = whereis(myport), + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Test that the 'eof' option works. + +eof(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(100)), + ?line PortTest = port_test(Config), + ?line Command = lists:concat([PortTest, " -h0 -q"]), + ?line P = open_port({spawn, Command}, [eof]), + ?line receive + {P, eof} -> + ok + end, + ?line P ! {self(), close}, + ?line receive + {P, closed} -> ok + end, + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Tests that the 'in' option for a port works. + +input_only(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(300)), + ?line expect_input(Config, [0, 1, 10, 13, 127, 128, 255], 1, "", [in]), + ?line expect_input(Config, [0, 1, 255, 2048], 2, "", [in]), + ?line expect_input(Config, [0, 1, 255, 2048], 4, "", [in]), + ?line expect_input(Config, [0, 1, 10, 13, 127, 128, 255], + 1, "", [in, binary]), + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Tests that the 'out' option for a port works. + +output_only(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(100)), + ?line Dir = ?config(priv_dir, Config), + ?line Filename = filename:join(Dir, "output_only_stream"), + ?line output_and_verify(Config, Filename, "-h0", + random_packet(35777, "echo")), + ?line test_server:timetrap_cancel(Dog), + ok. + +output_and_verify(Config, Filename, Options, Data) -> + ?line PortTest = port_test(Config), + ?line Command = lists:concat([PortTest, " ", + Options, " -o", Filename]), + ?line Port = open_port({spawn, Command}, [out]), + ?line Port ! {self(), {command, Data}}, + ?line Port ! {self(), close}, + ?line receive + {Port, closed} -> ok + end, + Wait_time = case os:type() of + vxworks -> 5000; + _ -> 500 + end, + ?line test_server:sleep(Wait_time), + ?line {ok, Written} = file:read_file(Filename), + ?line Data = binary_to_list(Written), + ok. + +%% Test that receiving several packages written in the same +%% write operation works. + +multiple_packets(suite) -> [mul_basic, mul_slow_writes]. + +%% Basic test of receiving multiple packages, written in +%% one operation by the other end. +mul_basic(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(600)), + case os:type() of + vxworks -> + %% don't stress vxworks too much + ?line expect_input(Config, [0, 1, 255, 10, 13], 1, "", []), + ?line expect_input(Config, [0, 10, 13, 1600, 8191, 16383], 2, "", []), + ?line expect_input(Config, [10, 35000], 4, "", []); + _ -> + ?line expect_input(Config, [0, 1, 255, 10, 13], 1, "", []), + ?line expect_input(Config, [0, 10, 13, 1600, 32767, 65535], 2, "", []), + ?line expect_input(Config, [10, 70000], 4, "", []) + end, + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Test reading a buffer consisting of several packets, some +%% of which might be incomplete. (The port program builds +%% a buffer with several packets, but writes it in chunks with +%% delays in between.) + +mul_slow_writes(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(250)), + ?line expect_input(Config, [0, 20, 255, 10, 1], 1, "-s64", []), + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Runs several port tests in parallell. Each individual test +%% finishes in about 5 seconds. Running in parallell, all tests +%% should also finish in about 5 seconds. + +parallell(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(300)), + ?line Testers = + [fun() -> stream_ping(Config, 1007, "-s100", []) end, + fun() -> stream_ping(Config, 10007, "-s1000", []) end, + fun() -> stream_ping(Config, 10007, "-s1000", []) end, + + fun() -> expect_input(Config, [21, 22, 23, 24, 25], 1, + "-s10", [in]) end, + + fun() -> ping(Config, [10], 1, "-d", []) end, + fun() -> ping(Config, [20000], 2, "-d", []) end, + fun() -> ping(Config, [101], 1, "-s10", []) end, + fun() -> ping(Config, [1001], 2, "-s100", []) end, + fun() -> ping(Config, [10001], 4, "-s1000", []) end, + + fun() -> ping(Config, [501, 501], 2, "-s100", []) end, + fun() -> ping(Config, [11, 12, 13, 14, 11], 1, "-s5", []) end], + ?line process_flag(trap_exit, true), + ?line Pids = lists:map(fun fun_spawn/1, Testers), + ?line wait_for(Pids), + ?line test_server:timetrap_cancel(Dog), + ok. + +wait_for([]) -> + ok; +wait_for(Pids) -> + io:format("Waiting for ~p", [Pids]), + receive + {'EXIT', Pid, normal} -> + wait_for(lists:delete(Pid, Pids)); + Other -> + test_server:fail({bad_exit, Other}) + end. + +%% Tests starting port programs that terminate by themselves. +%% This used to cause problems on Windows. + +dying_port(suite) -> []; +dying_port(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(150)), + ?line process_flag(trap_exit, true), + + ?line P1 = make_dying_port(Config), + ?line P2 = make_dying_port(Config), + ?line P3 = make_dying_port(Config), + ?line P4 = make_dying_port(Config), + ?line P5 = make_dying_port(Config), + + %% This should be big enough to be sure to block in the write. + ?line Garbage = random_packet(16384), + + ?line P1 ! {self(), {command, Garbage}}, + ?line P3 ! {self(), {command, Garbage}}, + ?line P5 ! {self(), {command, Garbage}}, + + ?line wait_for_port_exit(P1), + ?line wait_for_port_exit(P2), + ?line wait_for_port_exit(P3), + ?line wait_for_port_exit(P4), + ?line wait_for_port_exit(P5), + + ?line test_server:timetrap_cancel(Dog), + ok. + +wait_for_port_exit(Port) -> + receive + {'EXIT', Port, _} -> + ok + end. + +make_dying_port(Config) when is_list(Config) -> + PortTest = port_test(Config), + Command = lists:concat([PortTest, " -h0 -d -q"]), + open_port({spawn, Command}, [stream]). + +%% Tests that port program with complete path (but without any +%% .exe extension) can be started, even if there is a file with +%% the same name but without the extension in the same directory. +%% (In practice, the file with the same name could be a Unix +%% executable.) +%% +%% This used to failed on Windows (the .exe extension had to be +%% explicitly given). +%% +%% This testcase works on Unix, but is not very useful. + +port_program_with_path(suite) -> []; +port_program_with_path(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(100)), + ?line DataDir = ?config(data_dir, Config), + ?line PrivDir = ?config(priv_dir, Config), + + %% Create a copy of the port test program in a directory not + %% included in PATH (i.e. in priv_dir), with the name 'my_port_test.exe'. + %% Also, place a file named 'my_port_test' in the same directory. + %% This used to confuse the CreateProcess() call in spawn driver. + %% (On Unix, there will be a single file created, which will be + %% a copy of the port program.) + + ?line PortTest = os:find_executable("port_test", DataDir), + io:format("os:find_executable(~p, ~p) returned ~p", + ["port_test", DataDir, PortTest]), + ?line {ok, PortTestPgm} = file:read_file(PortTest), + ?line NewName = filename:join(PrivDir, filename:basename(PortTest)), + ?line RedHerring = filename:rootname(NewName), + ?line ok = file:write_file(RedHerring, "I'm just here to confuse.\n"), + ?line ok = file:write_file(NewName, PortTestPgm), + ?line ok = file:write_file_info(NewName, #file_info{mode=8#111}), + ?line PgmWithPathAndNoExt = filename:rootname(NewName), + + %% Open the port using the path to the copied port test program, + %% but without the .exe extension, and verified that it was started. + %% + %% If the bug is present the open_port call will fail with badarg. + + ?line Command = lists:concat([PgmWithPathAndNoExt, " -h2"]), + %% allow VxWorks time to write file + case os:type() of + vxworks -> test_server:sleep(2500); + _ -> time + end, + ?line P = open_port({spawn, Command}, [{packet, 2}]), + ?line Message = "echo back to me", + ?line P ! {self(), {command, Message}}, + ?line receive + {P, {data, Message}} -> + ok + end, + ?line test_server:timetrap_cancel(Dog), + ok. + + +%% Tests that files can be read using open_port(Filename, [in]). +%% This used to fail on Windows. +open_input_file_port(suite) -> []; +open_input_file_port(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line PrivDir = ?config(priv_dir, Config), + + %% Create a file with the file driver and read it back using + %% open_port/2. + + ?line MyFile1 = filename:join(PrivDir, "my_input_file"), + ?line FileData1 = "An input file", + ?line ok = file:write_file(MyFile1, FileData1), + case os:type() of + vxworks -> + %% Can't open input file with vanilla driver on VxWorks + ?line process_flag(trap_exit, true), + ?line case catch open_port(MyFile1, [in]) of + {'EXIT', {badarg, _}} -> + ok + end; + _ -> + ?line case open_port(MyFile1, [in]) of + InputPort when is_port(InputPort) -> + ?line receive + {InputPort, {data, FileData1}} -> + ok + end + end + end, + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Tests that files can be written using open_port(Filename, [out]). +open_output_file_port(suite) -> []; +open_output_file_port(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(100)), + ?line PrivDir = ?config(priv_dir, Config), + + %% Create a file with open_port/2 and read it back with + %% the file driver. + + ?line MyFile2 = filename:join(PrivDir, "my_output_file"), + ?line FileData2_0 = "A file created ", + ?line FileData2_1 = "with open_port/2.\n", + ?line FileData2 = FileData2_0 ++ FileData2_1, + ?line OutputPort = open_port(MyFile2, [out]), + ?line OutputPort ! {self(), {command, FileData2_0}}, + ?line OutputPort ! {self(), {command, FileData2_1}}, + ?line OutputPort ! {self(), close}, + ?line {ok, Bin} = file:read_file(MyFile2), + ?line FileData2 = binary_to_list(Bin), + + ?line test_server:timetrap_cancel(Dog), + ok. + +%% +%% Open as many ports as possible. Do this several times and check +%% that we get the same number of ports every time. +%% + +iter_max_ports(suite) -> []; +iter_max_ports(Config) when is_list(Config) -> + %% The child_setup program might dump core if we get out of memory. + %% This is hard to do anything about and is harmless. We run this test + %% in a working directory with an ignore_core_files file which will make + %% the search for core files ignore cores generated by this test. + %% + Config2 = ignore_cores:setup(?MODULE, iter_max_ports, Config, true), + try + iter_max_ports_test(Config2) + after + ignore_cores:restore(Config2) + end. + + +iter_max_ports_test(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(20)), + ?line PortTest = port_test(Config), + ?line Command = lists:concat([PortTest, " -h0 -q"]), + ?line Iters = case os:type() of + {win32,_} -> 4; + _ -> 10 + end, + ?line L = do_iter_max_ports(Iters, Command), + io:format("Result: ~p",[L]), + ?line all_equal(L), + ?line test_server:timetrap_cancel(Dog), + {comment, "Max ports: " ++ integer_to_list(hd(L))}. + +do_iter_max_ports(N, Command) when N > 0 -> + [max_ports(Command)| do_iter_max_ports(N-1, Command)]; +do_iter_max_ports(_, _) -> + []. + +all_equal([E,E|T]) -> + all_equal([E|T]); +all_equal([_]) -> ok; +all_equal([]) -> ok. + +max_ports(Command) -> + test_server:sleep(500), + ?line Ps = open_ports({spawn, Command}, [eof]), + ?line N = length(Ps), + ?line close_ports(Ps), + io:format("Got ~p ports\n",[N]), + N. + +close_ports([P|Ps]) -> + P ! {self(), close}, + receive + {P,closed} -> + ok + end, + close_ports(Ps); +close_ports([]) -> + ok. + +open_ports(Name, Settings) -> + test_server:sleep(50), + case catch open_port(Name, Settings) of + P when is_port(P) -> + [P| open_ports(Name, Settings)]; + {'EXIT', {Code, _}} -> + case Code of + enfile -> + []; + emfile -> + []; + system_limit -> + []; + Other -> + ?line test_server:fail({open_ports, Other}) + end; + Other -> + ?line test_server:fail({open_ports, Other}) + end. + +%% Tests that exit(Port, Term) works (has been known to crash the emulator). + +t_exit(suite) -> []; +t_exit(Config) when is_list(Config) -> + ?line process_flag(trap_exit, true), + ?line Pid = fun_spawn(fun suicide_port/1, [Config]), + ?line receive + {'EXIT', Pid, die} -> + ok; + Other -> + test_server:fail({bad_message, Other}) + end. + +suicide_port(Config) when is_list(Config) -> + ?line Port = port_expect(Config, [], 0, "", []), + ?line exit(Port, die), + ?line receive after infinity -> ok end. + +tps(suite) -> [tps_16_bytes, tps_1K]. + +tps_16_bytes(doc) -> ""; +tps_16_bytes(suite) -> []; +tps_16_bytes(Config) when is_list(Config) -> + ?line tps(16, Config). + +tps_1K(doc) -> ""; +tps_1K(suite) -> []; +tps_1K(Config) when is_list(Config) -> + ?line tps(1024, Config). + +tps(Size, Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(300)), + ?line PortTest = port_test(Config), + ?line Packet = list_to_binary(random_packet(Size, "e")), + ?line Port = open_port({spawn, PortTest}, [binary, {packet, 2}]), + ?line Transactions = 10000, + ?line {Elapsed, ok} = test_server:timecall(?MODULE, tps, + [Port, Packet, Transactions]), + ?line test_server:timetrap_cancel(Dog), + {comment, integer_to_list(trunc(Transactions/Elapsed+0.5)) ++ " transactions/s"}. + +tps(_Port, _Packet, 0) -> ok; +tps(Port, Packet, N) -> + ?line port_command(Port, Packet), + ?line receive + {Port, {data, Packet}} -> + ?line tps(Port, Packet, N-1); + Other -> + ?line test_server:fail({bad_message, Other}) + end. + +%% Line I/O test +line(Config) when is_list(Config) -> + ?line Siz = 110, + ?line Dog = test_server:timetrap(test_server:seconds(300)), + ?line Packet1 = random_packet(Siz), + ?line Packet2 = random_packet(Siz div 2), + %% Test that packets are split into lines + ?line port_expect(Config,[{lists:append([Packet1, io_lib:nl(), Packet2, + io_lib:nl()]), + [{eol, Packet1}, {eol, Packet2}]}], + 0, "", [{line,Siz}]), + %% Test the same for binaries + ?line port_expect(Config,[{lists:append([Packet1, io_lib:nl(), Packet2, + io_lib:nl()]), + [{eol, Packet1}, {eol, Packet2}]}], + 0, "", [{line,Siz},binary]), + %% Test that too long lines get split + ?line port_expect(Config,[{lists:append([Packet1, io_lib:nl(), Packet1, + Packet2, io_lib:nl()]), + [{eol, Packet1}, {noeol, Packet1}, + {eol, Packet2}]}], 0, "", [{line,Siz}]), + %% Test that last output from closing port program gets received. + ?line L1 = lists:append([Packet1, io_lib:nl(), Packet2]), + ?line S1 = lists:flatten(io_lib:format("-l~w", [length(L1)])), + io:format("S1 = ~w, L1 = ~w~n", [S1,L1]), + ?line port_expect(Config,[{L1, + [{eol, Packet1}, {noeol, Packet2}, eof]}], 0, + S1, [{line,Siz},eof]), + %% Test that lonely <CR> Don't get treated as newlines + ?line port_expect(Config,[{lists:append([Packet1, [13], Packet2, + io_lib:nl()]), + [{noeol, Packet1}, {eol, [13 |Packet2]}]}], + 0, "", [{line,Siz}]), + %% Test that packets get built up to lines (delayed output from + %% port program) + ?line port_expect(Config,[{Packet2,[]}, + {lists:append([Packet2, io_lib:nl(), + Packet1, io_lib:nl()]), + [{eol, lists:append(Packet2, Packet2)}, + {eol, Packet1}]}], 0, "-d", [{line,Siz}]), + %% Test that we get badarg if trying both packet and line + ?line bad_argument(Config, [{packet, 5}, {line, 5}]), + ?line test_server:timetrap_cancel(Dog), + ok. + +%%% Redirection of stderr test +stderr_to_stdout(suite) -> + []; +stderr_to_stdout(doc) -> + "Test that redirection of standard error to standard output works."; +stderr_to_stdout(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(60)), + %% See that it works + ?line Packet = random_packet(10), + ?line port_expect(Config,[{Packet,[Packet]}], 0, "-e -l10", + [stderr_to_stdout]), + %% ?line stream_ping(Config, 10, "-e", [stderr_to_stdout]), + %% See that it doesn't always happen (will generate garbage on stderr) + ?line port_expect(Config,[{Packet,[eof]}], 0, "-e -l10", [line,eof]), + ?line test_server:timetrap_cancel(Dog), + ok. + + +bad_argument(Config, ArgList) -> + PortTest = port_test(Config), + case catch open_port({spawn, PortTest}, ArgList) of + {'EXIT', {badarg, _}} -> + ok + end. + + +%% 'env' option +%% (Can perhaps be made smaller by calling the other utility functions +%% in this module.) +env(suite) -> + []; +env(doc) -> + ["Test that the 'env' option works"]; +env(Config) when is_list(Config) -> + case os:type() of + vxworks -> + {skipped,"Environments not implemented on VxWorks (could be...)"}; + _ -> + env2(Config) + end. + +env2(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(60)), + ?line Priv = ?config(priv_dir, Config), + ?line Temp = filename:join(Priv, "env_fun.bin"), + + PluppVal = "dirty monkey", + ?line env_slave(Temp, [{"plupp",PluppVal}]), + + Long = "LongAndBoringEnvName", + ?line os:putenv(Long, "nisse"), + + ?line env_slave(Temp, [{"plupp",PluppVal}, + {"DIR_PLUPP","###glurfrik"}], + fun() -> + PluppVal = os:getenv("plupp"), + "###glurfrik" = os:getenv("DIR_PLUPP"), + "nisse" = os:getenv(Long) + end), + + + ?line env_slave(Temp, [{"must_define_something","some_value"}, + {"certainly_not_existing",false}, + {Long,false}, + {"glurf","a glorfy string"}]), + + ?line test_server:timetrap_cancel(Dog), + ok. + +env_slave(File, Env) -> + F = fun() -> + lists:foreach(fun({Name,Val}) -> + Val = os:getenv(Name) + end, Env) + end, + env_slave(File, Env, F). + +env_slave(File, Env, Body) -> + file:write_file(File, term_to_binary(Body)), + Program = atom_to_list(lib:progname()), + Dir = filename:dirname(code:which(?MODULE)), + Cmd = Program ++ " -pz " ++ Dir ++ + " -noinput -run " ++ ?MODULE_STRING ++ " env_slave_main " ++ + File ++ " -run erlang halt", + Port = open_port({spawn, Cmd}, [{env,Env},{line,256}]), + receive + {Port,{data,{eol,"ok"}}} -> + ok; + {Port,{data,{eol,Error}}} -> + io:format("~p\n", [Error]), + test_server:fail(); + Other -> + test_server:fail(Other) + end. + +env_slave_main([File]) -> + {ok,Body0} = file:read_file(File), + Body = binary_to_term(Body0), + case Body() of + {'EXIT',Reason} -> + io:format("Error: ~p\n", [Reason]); + _ -> + io:format("ok\n") + end, + init:stop(). + + +%% 'env' option +%% Test bad environments. +bad_env(Config) when is_list(Config) -> + case os:type() of + vxworks -> + {skipped,"Environments not implemented on VxWorks"}; + _ -> + bad_env_1() + end. + +bad_env_1() -> + ?line try_bad_env([abbb]), + ?line try_bad_env([{"key","value"}|{"another","value"}]), + ?line try_bad_env([{"key","value","value2"}]), + ?line try_bad_env([{"key",[a,b,c]}]), + ?line try_bad_env([{"key",value}]), + ?line try_bad_env({a,tuple}), + ?line try_bad_env(42), + ?line try_bad_env([a|b]), + ?line try_bad_env(self()), + ok. + +try_bad_env(Env) -> + try open_port({spawn,"ls"}, [{env,Env}]) + catch + error:badarg -> ok + end. + +%% 'cd' option +%% (Can perhaps be made smaller by calling the other utility functions +%% in this module.) +cd(suite) -> + []; +cd(doc) -> + ["Test that the 'cd' option works"]; +cd(Config) when is_list(Config) -> + case os:type() of + vxworks -> + {skipped,"Task specific directories does not exist on VxWorks"}; + _ -> + cd2(Config) + end. +cd2(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(60)), + + ?line Program = atom_to_list(lib:progname()), + ?line DataDir = ?config(data_dir, Config), + ?line TestDir = filename:join(DataDir, "dir"), + ?line Cmd = Program ++ " -pz " ++ DataDir ++ + " -noshell -s port_test pwd -s erlang halt", + ?line _ = open_port({spawn, Cmd}, + [{cd, TestDir}, + {line, 256}]), + ?line receive + {_, {data, {eol, String}}} -> + case filename_equal(String, TestDir) of + true -> + ok; + false -> + ?line test_server:fail({cd, String}) + end; + Other2 -> + ?line test_server:fail({env, Other2}) + end, + + ?line test_server:timetrap_cancel(Dog), + ok. + +filename_equal(A, B) -> + case os:type() of + {win32, _} -> + win_filename_equal(A, B); + _ -> + A == B + end. + +win_filename_equal([], []) -> + true; +win_filename_equal([], _) -> + false; +win_filename_equal(_, []) -> + false; +win_filename_equal([C1 | Rest1], [C2 | Rest2]) -> + case tolower(C1) == tolower(C2) of + true -> + win_filename_equal(Rest1, Rest2); + false -> + false + end. + +tolower(C) when C >= $A, C =< $Z -> + C + 32; +tolower(C) -> + C. + +otp_3906(suite) -> + []; +otp_3906(doc) -> + ["Tests that child process deaths are managed correctly when there are " + " a large amount of concurrently dying children. See ticket OTP-3906."]; +otp_3906(Config) when is_list(Config) -> + case os:type() of + {unix, OSName} -> + otp_3906(Config, OSName); + _ -> + {skipped, "Only run on Unix systems"} + end. + +-define(OTP_3906_CHILDREN, 1000). +-define(OTP_3906_EXIT_STATUS, 17). +-define(OTP_3906_PROGNAME, "otp_3906"). +-define(OTP_3906_TICK_TIMEOUT, 5000). +-define(OTP_3906_OSP_P_ERLP, 10). +-define(OTP_3906_MAX_CONC_OSP, 50). + +otp_3906(Config, OSName) -> + ?line TSDir = filename:dirname(code:which(test_server)), + ?line {ok, Variables} = file:consult(filename:join(TSDir, "variables")), + case lists:keysearch('CC', 1, Variables) of + {value,{'CC', CC}} -> + SuiteDir = filename:dirname(code:which(?MODULE)), + PrivDir = ?config(priv_dir, Config), + Prog = otp_3906_make_prog(CC, PrivDir), + {ok, Node} = test_server:start_node(otp_3906, + slave, + [{args, " -pa " ++ SuiteDir}, + {linked, false}]), + OP = process_flag(priority, max), + OTE = process_flag(trap_exit, true), + FS = spawn_link(Node, + ?MODULE, + otp_3906_start_forker_starter, + [?OTP_3906_CHILDREN, [], self(), Prog]), + Result = receive + {'EXIT', _ForkerStarter, Reason} -> + {failed, Reason}; + {emulator_pid, EmPid} -> + case otp_3906_wait_result(FS, 0, 0) of + {succeded, + ?OTP_3906_CHILDREN, + ?OTP_3906_CHILDREN} -> + succeded; + {succeded, Forked, Exited} -> + otp_3906_list_defunct(EmPid, OSName), + {failed, + {mismatch, + {forked, Forked}, + {exited, Exited}}}; + Res -> + otp_3906_list_defunct(EmPid, OSName), + Res + end + end, + process_flag(trap_exit, OTE), + process_flag(priority, OP), + test_server:stop_node(Node), + case Result of + succeded -> + ok; + _ -> + ?line test_server:fail(Result) + end; + _ -> + {skipped, "No C compiler found"} + end. + +otp_3906_list_defunct(EmPid, OSName) -> + % Guess ps switches to use and what to grep for (could be improved) + {Switches, Zombie} = case OSName of + BSD when BSD == darwin; + BSD == openbsd; + BSD == netbsd; + BSD == freebsd -> + {"-ajx", "Z"}; + _ -> + {"-ef", "[dD]efunct"} + end, + test_server:format("Emulator pid: ~s~n" + "Listing of zombie processes:~n" + "~s~n", + [EmPid, + otp_3906_htmlize(os:cmd("ps " + ++ Switches + ++ " | grep " + ++ Zombie))]). + +otp_3906_htmlize([]) -> + []; +otp_3906_htmlize([C | Cs]) -> + case [C] of + "<" -> "<" ++ otp_3906_htmlize(Cs); + ">" -> ">" ++ otp_3906_htmlize(Cs); + _ -> [C | otp_3906_htmlize(Cs)] + end. + +otp_3906_make_prog(CC, PrivDir) -> + SrcFileName = filename:join(PrivDir, ?OTP_3906_PROGNAME ++ ".c"), + TrgtFileName = filename:join(PrivDir, ?OTP_3906_PROGNAME), + {ok, SrcFile} = file:open(SrcFileName, write), + io:format(SrcFile, + "int ~n" + "main(void) ~n" + "{ ~n" + " return ~p; ~n" + "} ~n", + [?OTP_3906_EXIT_STATUS]), + file:close(SrcFile), + os:cmd(CC ++ " " ++ SrcFileName ++ " -o " ++ TrgtFileName), + TrgtFileName. + + +otp_3906_wait_result(ForkerStarter, F, E) -> + receive + {'EXIT', ForkerStarter, Reason} -> + {failed, {Reason, {forked, F}, {exited, E}}}; + forked -> + otp_3906_wait_result(ForkerStarter, F+1, E); + exited -> + otp_3906_wait_result(ForkerStarter, F, E+1); + tick -> + otp_3906_wait_result(ForkerStarter, F, E); + succeded -> + {succeded, F, E} + after + ?OTP_3906_TICK_TIMEOUT -> + unlink(ForkerStarter), + exit(ForkerStarter, timeout), + {failed, {timeout, {forked, F}, {exited, E}}} + end. + +otp_3906_collect([], _) -> + done; +otp_3906_collect(RefList, Sup) -> + otp_3906_collect(otp_3906_collect_one(RefList, Sup), Sup). + +otp_3906_collect_one(RefList, Sup) -> + receive + Ref when is_reference(Ref) -> + Sup ! tick, + lists:delete(Ref, RefList) + end. + +otp_3906_start_forker(N, Sup, Prog) -> + Ref = make_ref(), + spawn_opt(?MODULE, + otp_3906_forker, + [N, self(), Ref, Sup, Prog], + [link, {priority, max}]), + Ref. + +otp_3906_start_forker_starter(N, RefList, Sup, Prog) -> + process_flag(priority, max), + EmPid = os:getpid(), + Sup ! {emulator_pid, EmPid}, + otp_3906_forker_starter(N, RefList, Sup, Prog). + +otp_3906_forker_starter(0, RefList, Sup, _) -> + otp_3906_collect(RefList, Sup), + unlink(Sup), + Sup ! succeded; +otp_3906_forker_starter(N, RefList, Sup, Prog) + when length(RefList) >= ?OTP_3906_MAX_CONC_OSP -> + otp_3906_forker_starter(N, otp_3906_collect_one(RefList, Sup), Sup, Prog); +otp_3906_forker_starter(N, RefList, Sup, Prog) + when is_integer(N), N > ?OTP_3906_OSP_P_ERLP -> + otp_3906_forker_starter(N-?OTP_3906_OSP_P_ERLP, + [otp_3906_start_forker(?OTP_3906_OSP_P_ERLP, + Sup, + Prog)|RefList], + Sup, + Prog); +otp_3906_forker_starter(N, RefList, Sup, Prog) when is_integer(N) -> + otp_3906_forker_starter(0, + [otp_3906_start_forker(N, + Sup, + Prog)|RefList], + Sup, + Prog). + +otp_3906_forker(0, Parent, Ref, _, _) -> + unlink(Parent), + Parent ! Ref; +otp_3906_forker(N, Parent, Ref, Sup, Prog) -> + Port = erlang:open_port({spawn, Prog}, [exit_status, in]), + Sup ! forked, + receive + {Port, {exit_status, ?OTP_3906_EXIT_STATUS}} -> + Sup ! exited, + otp_3906_forker(N-1, Parent, Ref, Sup, Prog); + {Port, Res} -> + exit(Res); + Other -> + exit(Other) + end. + + +otp_4389(suite) -> []; +otp_4389(doc) -> []; +otp_4389(Config) when is_list(Config) -> + case {os:type(),erlang:system_info(heap_type)} of + {{unix, _},private} -> + ?line Dog = test_server:timetrap(test_server:seconds(240)), + ?line TCR = self(), + case get_true_cmd() of + True when is_list(True) -> + ?line lists:foreach( + fun (P) -> + ?line receive + {P, ok} -> ?line ok; + {P, Err} -> ?line ?t:fail(Err) + end + end, + lists:map( + fun(_) -> + spawn_link( + fun() -> + process_flag(trap_exit, true), + case catch open_port({spawn, True}, + [stream,exit_status]) of + P when is_port(P) -> + receive + {P,{exit_status,_}} -> + TCR ! {self(),ok}; + {'EXIT',_,{R2,_}} when R2 == emfile; + R2 == eagain -> + TCR ! {self(),ok}; + Err2 -> + TCR ! {self(),{msg,Err2}} + end; + {'EXIT',{R1,_}} when R1 == emfile; + R1 == eagain -> + TCR ! {self(),ok}; + Err1 -> + TCR ! {self(), {open_port,Err1}} + end + end) + end, + lists:duplicate(1000,[]))), + ?line test_server:timetrap_cancel(Dog), + {comment, + "This test case doesn't always fail when the bug that " + "it tests for is present (it is most likely to fail on" + " a multi processor machine). If the test case fails it" + " will fail by deadlocking the emulator."}; + _ -> + ?line {skipped, "\"true\" command not found"} + end; + _ -> + {skip,"Only run on Unix and private heaps"} + end. + +get_true_cmd() -> + DoFileExist = fun (FileName) -> + case file:read_file_info(FileName) of + {ok, _} -> throw(FileName); + _ -> not_found + end + end, + catch begin + %% First check in /usr/bin and /bin + DoFileExist("/usr/bin/true"), + DoFileExist("/bin/true"), + %% Try which + case filename:dirname(os:cmd("which true")) of + "." -> not_found; + TrueDir -> filename:join(TrueDir, "true") + end + end. + +%% 'exit_status' option +exit_status(suite) -> + []; +exit_status(doc) -> + ["Test that the 'exit_status' option works"]; +exit_status(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(60)), + ?line port_expect(Config,[{"x", + [{exit_status, 5}]}], + 1, "", [exit_status]), + ?line test_server:timetrap_cancel(Dog), + ok. + +spawn_driver(suite) -> + []; +spawn_driver(doc) -> + ["Test spawning a driver specifically"]; +spawn_driver(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line ok = load_driver(Path, "echo_drv"), + ?line Port = erlang:open_port({spawn_driver, "echo_drv"}, []), + ?line Port ! {self(), {command, "Hello port!"}}, + ?line receive + {Port, {data, "Hello port!"}} = Msg1 -> + io:format("~p~n", [Msg1]), + ok; + Other -> + test_server:fail({unexpected, Other}) + end, + ?line Port ! {self(), close}, + ?line receive {Port, closed} -> ok end, + + ?line Port2 = erlang:open_port({spawn_driver, "echo_drv -Hello port?"}, + []), + ?line receive + {Port2, {data, "Hello port?"}} = Msg2 -> + io:format("~p~n", [Msg2]), + ok; + Other2 -> + test_server:fail({unexpected2, Other2}) + end, + ?line Port2 ! {self(), close}, + ?line receive {Port2, closed} -> ok end, + ?line {'EXIT',{badarg,_}} = (catch erlang:open_port({spawn_driver, "ls"}, [])), + ?line {'EXIT',{badarg,_}} = (catch erlang:open_port({spawn_driver, "cmd"}, [])), + ?line {'EXIT',{badarg,_}} = (catch erlang:open_port({spawn_driver, os:find_executable("erl")}, [])), + ?line test_server:timetrap_cancel(Dog), + ok. + +spawn_executable(suite) -> + []; +spawn_executable(doc) -> + ["Test spawning an executable specifically"]; +spawn_executable(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line DataDir = ?config(data_dir, Config), + ?line EchoArgs1 = filename:join([DataDir,"echo_args"]), + ?line ExactFile1 = filename:nativename(os:find_executable(EchoArgs1)), + ?line [ExactFile1] = run_echo_args(DataDir,[]), + ?line ["echo_args"] = run_echo_args(DataDir,["echo_args"]), + ?line ["echo_arguments"] = run_echo_args(DataDir,["echo_arguments"]), + ?line [ExactFile1,"hello world","dlrow olleh"] = + run_echo_args(DataDir,[ExactFile1,"hello world","dlrow olleh"]), + ?line [ExactFile1] = run_echo_args(DataDir,[default]), + ?line [ExactFile1,"hello world","dlrow olleh"] = + run_echo_args(DataDir,[switch_order,ExactFile1,"hello world", + "dlrow olleh"]), + ?line [ExactFile1,"hello world","dlrow olleh"] = + run_echo_args(DataDir,[default,"hello world","dlrow olleh"]), + + ?line [ExactFile1,"hello world","dlrow olleh"] = + run_echo_args_2("\""++ExactFile1++"\" "++"\"hello world\" \"dlrow olleh\""), + + ?line PrivDir = ?config(priv_dir, Config), + ?line SpaceDir =filename:join([PrivDir,"With Spaces"]), + ?line file:make_dir(SpaceDir), + ?line Executable = filename:basename(ExactFile1), + ?line file:copy(ExactFile1,filename:join([SpaceDir,Executable])), + ?line ExactFile2 = filename:nativename(filename:join([SpaceDir,Executable])), + ?line chmodplusx(ExactFile2), + io:format("|~s|~n",[ExactFile2]), + ?line [ExactFile2] = run_echo_args(SpaceDir,[]), + ?line ["echo_args"] = run_echo_args(SpaceDir,["echo_args"]), + ?line ["echo_arguments"] = run_echo_args(SpaceDir,["echo_arguments"]), + ?line [ExactFile2,"hello world","dlrow olleh"] = + run_echo_args(SpaceDir,[ExactFile2,"hello world","dlrow olleh"]), + ?line [ExactFile2] = run_echo_args(SpaceDir,[default]), + ?line [ExactFile2,"hello world","dlrow olleh"] = + run_echo_args(SpaceDir,[switch_order,ExactFile2,"hello world", + "dlrow olleh"]), + ?line [ExactFile2,"hello world","dlrow olleh"] = + run_echo_args(SpaceDir,[default,"hello world","dlrow olleh"]), + ?line [ExactFile2,"hello world","dlrow olleh"] = + run_echo_args_2("\""++ExactFile2++"\" "++"\"hello world\" \"dlrow olleh\""), + + ?line ExeExt = + case string:to_lower(lists:last(string:tokens(ExactFile2,"."))) of + "exe" -> + ".exe"; + _ -> + "" + end, + Executable2 = "spoky name"++ExeExt, + ?line file:copy(ExactFile1,filename:join([SpaceDir,Executable2])), + ?line ExactFile3 = filename:nativename(filename:join([SpaceDir,Executable2])), + ?line chmodplusx(ExactFile3), + ?line [ExactFile3] = run_echo_args(SpaceDir,Executable2,[]), + ?line ["echo_args"] = run_echo_args(SpaceDir,Executable2,["echo_args"]), + ?line ["echo_arguments"] = run_echo_args(SpaceDir,Executable2,["echo_arguments"]), + ?line [ExactFile3,"hello world","dlrow olleh"] = + run_echo_args(SpaceDir,Executable2,[ExactFile3,"hello world","dlrow olleh"]), + ?line [ExactFile3] = run_echo_args(SpaceDir,Executable2,[default]), + ?line [ExactFile3,"hello world","dlrow olleh"] = + run_echo_args(SpaceDir,Executable2, + [switch_order,ExactFile3,"hello world", + "dlrow olleh"]), + ?line [ExactFile3,"hello world","dlrow olleh"] = + run_echo_args(SpaceDir,Executable2, + [default,"hello world","dlrow olleh"]), + ?line [ExactFile3,"hello world","dlrow olleh"] = + run_echo_args_2("\""++ExactFile3++"\" "++"\"hello world\" \"dlrow olleh\""), + ?line {'EXIT',{enoent,_}} = (catch run_echo_args(SpaceDir,"fnurflmonfi", + [default,"hello world", + "dlrow olleh"])), + NonExec = "kronxfrt"++ExeExt, + ?line file:write_file(filename:join([SpaceDir,NonExec]), + <<"Not an executable">>), + ?line {'EXIT',{eacces,_}} = (catch run_echo_args(SpaceDir,NonExec, + [default,"hello world", + "dlrow olleh"])), + ?line {'EXIT',{enoent,_}} = (catch open_port({spawn_executable,"cmd"},[])), + ?line {'EXIT',{enoent,_}} = (catch open_port({spawn_executable,"sh"},[])), + case os:type() of + {win32,_} -> + test_bat_file(SpaceDir); + {unix,_} -> + test_sh_file(SpaceDir) + end, + ?line test_server:timetrap_cancel(Dog), + ok. + +test_bat_file(Dir) -> + FN = "tf.bat", + Full = filename:join([Dir,FN]), + D = [<<"@echo off\r\n">>, + <<"echo argv[0]:^|%0^|\r\n">>, + <<"if \"%1\" == \"\" goto done\r\n">>, + <<"echo argv[1]:^|%1^|\r\n">>, + <<"if \"%2\" == \"\" goto done\r\n">>, + <<"echo argv[2]:^|%2^|\r\n">>, + <<"if \"%3\" == \"\" goto done\r\n">>, + <<"echo argv[3]:^|%3^|\r\n">>, + <<"if \"%4\" == \"\" goto done\r\n">>, + <<"echo argv[4]:^|%4^|\r\n">>, + <<"if \"%5\" == \"\" goto done\r\n">>, + <<"echo argv[5]:^|%5^|\r\n">>, + <<"\r\n">>, + <<":done\r\n">>, + <<"\r\n">>], + ?line file:write_file(Full,list_to_binary(D)), + ?line EF = filename:basename(FN), + ?line [DN,"hello","world"] = + run_echo_args(Dir,FN, + [default,"hello","world"]), + %% The arg0 argumant should be ignored when running batch files + ?line [DN,"hello","world"] = + run_echo_args(Dir,FN, + ["knaskurt","hello","world"]), + ?line EF = filename:basename(DN), + ok. + +test_sh_file(Dir) -> + FN = "tf.sh", + Full = filename:join([Dir,FN]), + D = [<<"#! /bin/sh\n">>, + <<"echo 'argv[0]:|'$0'|'\n">>, + <<"i=1\n">>, + <<"while [ '!' -z \"$1\" ]; do\n">>, + <<" echo 'argv['$i']:|'\"$1\"'|'\n">>, + <<" shift\n">>, + <<" i=`expr $i + 1`\n">>, + <<"done\n">>], + ?line file:write_file(Full,list_to_binary(D)), + ?line chmodplusx(Full), + ?line [Full,"hello","world"] = + run_echo_args(Dir,FN, + [default,"hello","world"]), + ?line [Full,"hello","world of spaces"] = + run_echo_args(Dir,FN, + [default,"hello","world of spaces"]), + ?line file:write_file(filename:join([Dir,"testfile1"]),<<"testdata1">>), + ?line file:write_file(filename:join([Dir,"testfile2"]),<<"testdata2">>), + ?line Pattern = filename:join([Dir,"testfile*"]), + ?line L = filelib:wildcard(Pattern), + ?line 2 = length(L), + ?line [Full,"hello",Pattern] = + run_echo_args(Dir,FN, + [default,"hello",Pattern]), + ok. + + + +chmodplusx(Filename) -> + case file:read_file_info(Filename) of + {ok,FI} -> + FI2 = FI#file_info{mode = ((FI#file_info.mode) bor 8#00100)}, + file:write_file_info(Filename,FI2); + _ -> + ok + end. + +run_echo_args_2(FullnameAndArgs) -> + Port = open_port({spawn,FullnameAndArgs},[eof]), + Data = collect_data(Port), + Port ! {self(), close}, + receive {Port, closed} -> ok end, + parse_echo_args_output(Data). + + +run_echo_args(Where,Args) -> + run_echo_args(Where,"echo_args",Args). +run_echo_args(Where,Prog,Args) -> + ArgvArg = case Args of + [] -> + []; + [default|T] -> + [{args,T}]; + [switch_order,H|T] -> + [{args,T},{arg0,H}]; + [H|T] -> + [{arg0,H},{args,T}] + end, + Command = filename:join([Where,Prog]), + Port = open_port({spawn_executable,Command},ArgvArg++[eof]), + Data = collect_data(Port), + Port ! {self(), close}, + receive {Port, closed} -> ok end, + parse_echo_args_output(Data). + +collect_data(Port) -> + receive + {Port, {data, Data}} -> + Data ++ collect_data(Port); + {Port, eof} -> + [] + end. + +parse_echo_args_output(Data) -> + [lists:last(string:tokens(S,"|")) || S <- string:tokens(Data,"\r\n")]. + +mix_up_ports(suite) -> + []; +mix_up_ports(doc) -> + ["Test that the emulator does not mix up ports when the port table wraps"]; +mix_up_ports(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line ok = load_driver(Path, "echo_drv"), + ?line Port = erlang:open_port({spawn, "echo_drv"}, []), + ?line Port ! {self(), {command, "Hello port!"}}, + ?line receive + {Port, {data, "Hello port!"}} = Msg1 -> + io:format("~p~n", [Msg1]), + ok; + Other -> + test_server:fail({unexpected, Other}) + end, + ?line Port ! {self(), close}, + ?line receive {Port, closed} -> ok end, + ?line loop(start, done, + fun(P) -> + ?line Q = + (catch erlang:open_port({spawn, "echo_drv"}, [])), +%% ?line io:format("~p ", [Q]), + if is_port(Q) -> + Q; + true -> + io:format("~p~n", [P]), + done + end + end), + ?line Port ! {self(), {command, "Hello again port!"}}, + ?line receive + Msg2 -> + test_server:fail({unexpected, Msg2}) + after 1000 -> + ok + end, + ?line test_server:timetrap_cancel(Dog), + ok. + +loop(Stop, Stop, Fun) when is_function(Fun) -> + ok; +loop(Start, Stop, Fun) when is_function(Fun) -> + loop(Fun(Start), Stop, Fun). + + +otp_5112(suite) -> + []; +otp_5112(doc) -> + ["Test that link to connected process is taken away when port calls", + "driver_exit() also when the port index has wrapped"]; +otp_5112(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line ok = load_driver(Path, "exit_drv"), + ?line Port = otp_5112_get_wrapped_port(), + ?line ?t:format("Max ports: ~p~n",[max_ports()]), + ?line ?t:format("Port: ~p~n",[Port]), + ?line {links, Links1} = process_info(self(),links), + ?line ?t:format("Links1: ~p~n",[Links1]), + ?line true = lists:member(Port, Links1), + ?line Port ! {self(), {command, ""}}, + ?line {links, Links2} = process_info(self(),links), + ?line ?t:format("Links2: ~p~n",[Links2]), + ?line false = lists:member(Port, Links2), %% This used to fail + ?line test_server:timetrap_cancel(Dog), + ok. + +otp_5112_get_wrapped_port() -> + ?line P1 = erlang:open_port({spawn, "exit_drv"}, []), + ?line case port_ix(P1) < max_ports() of + true -> + ?line ?t:format("Need to wrap port index (~p)~n", [P1]), + ?line otp_5112_wrap_port_ix([P1]), + ?line P2 = erlang:open_port({spawn, "exit_drv"}, []), + ?line false = port_ix(P2) < max_ports(), + ?line P2; + false -> + ?line ?t:format("Port index already wrapped (~p)~n", [P1]), + ?line P1 + end. + +otp_5112_wrap_port_ix(Ports) -> + ?line case (catch erlang:open_port({spawn, "exit_drv"}, [])) of + Port when is_port(Port) -> + ?line otp_5112_wrap_port_ix([Port|Ports]); + _ -> + %% Port table now full; empty port table + ?line lists:foreach(fun (P) -> P ! {self(), close} end, + Ports), + ?line ok + end. + + +otp_5119(suite) -> + []; +otp_5119(doc) -> + ["Test that port index is not unnecessarily wrapped"]; +otp_5119(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line ok = load_driver(Path, "exit_drv"), + ?line PI1 = port_ix(otp_5119_fill_empty_port_tab([])), + ?line PI2 = port_ix(erlang:open_port({spawn, "exit_drv"}, [])), + ?line {PortIx1, PortIx2} + = case PI2 > PI1 of + true -> + ?line {PI1, PI2}; + false -> + ?line {port_ix(otp_5119_fill_empty_port_tab([PI2])), + port_ix(erlang:open_port({spawn, "exit_drv"}, []))} + end, + ?line MaxPorts = max_ports(), + ?line ?t:format("PortIx1 = ~p ~p~n", [PI1, PortIx1]), + ?line ?t:format("PortIx2 = ~p ~p~n", [PI2, PortIx2]), + ?line ?t:format("MaxPorts = ~p~n", [MaxPorts]), + ?line true = PortIx2 > PortIx1, + ?line true = PortIx2 =< PortIx1 + MaxPorts, + ?line test_server:timetrap_cancel(Dog), + ?line ok. + +otp_5119_fill_empty_port_tab(Ports) -> + ?line case (catch erlang:open_port({spawn, "exit_drv"}, [])) of + Port when is_port(Port) -> + ?line otp_5119_fill_empty_port_tab([Port|Ports]); + _ -> + %% Port table now full; empty port table + ?line lists:foreach(fun (P) -> P ! {self(), close} end, + Ports), + ?line [LastPort|_] = Ports, + ?line LastPort + end. + +-define(DEF_MAX_PORTS, 1024). + +max_ports_env() -> + ?line case os:getenv("ERL_MAX_PORTS") of + EMP when is_list(EMP) -> + case catch list_to_integer(EMP) of + Int when is_integer(Int) -> ?line Int; + _ -> ?line false + end; + _ -> ?line false + end. + +max_ports() -> + ?line PreMaxPorts + = case max_ports_env() of + Env when is_integer(Env) -> ?line Env; + _ -> + ?line case os:type() of + {unix, _} -> + ?line UlimStr = string:strip(os:cmd("ulimit -n") + -- "\n"), + ?line case catch list_to_integer(UlimStr) of + Ulim when is_integer(Ulim) -> ?line Ulim; + _ -> ?line ?DEF_MAX_PORTS + end; + _ -> ?line ?DEF_MAX_PORTS + end + end, + ?line case PreMaxPorts > ?DEF_MAX_PORTS of + true -> ?line PreMaxPorts; + false -> ?line ?DEF_MAX_PORTS + end. + +port_ix(Port) when is_port(Port) -> + ?line ["#Port",_,PortIxStr] = string:tokens(erlang:port_to_list(Port), + "<.>"), + ?line list_to_integer(PortIxStr). + + +otp_6224(doc) -> ["Check that port command failure doesn't crash the emulator"]; +otp_6224(suite) -> []; +otp_6224(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Path = ?config(data_dir, Config), + ?line ok = load_driver(Path, "failure_drv"), + ?line Go = make_ref(), + ?line Failer = spawn(fun () -> + receive Go -> ok end, + ?line Port = open_port({spawn, "failure_drv"}, + []), + Port ! {self(), {command, "Fail, please!"}}, + otp_6224_loop() + end), + ?line Mon = erlang:monitor(process, Failer), + ?line Failer ! Go, + ?line receive + {'DOWN', Mon, process, Failer, Reason} -> + ?line case Reason of + {driver_failed, _} -> ?line ok; + driver_failed -> ?line ok; + _ -> ?line ?t:fail({unexpected_exit_reason, + Reason}) + end + end, + ?line test_server:timetrap_cancel(Dog), + ?line ok. + +otp_6224_loop() -> + receive _ -> ok after 0 -> ok end, + otp_6224_loop(). + + +-define(EXIT_STATUS_MSB_MAX_PROCS, 64). +-define(EXIT_STATUS_MSB_MAX_PORTS, 300). + +exit_status_multi_scheduling_block(doc) -> []; +exit_status_multi_scheduling_block(suite) -> []; +exit_status_multi_scheduling_block(Config) when is_list(Config) -> + ?line Repeat = 3, + ?line case ?t:os_type() of + {unix, _} -> + ?line Dog = ?t:timetrap(test_server:minutes(2*Repeat)), + ?line SleepSecs = 6, + try + lists:foreach(fun (_) -> + exit_status_msb_test(Config, + SleepSecs) + end, + lists:seq(1, Repeat)) + after + %% Wait for the system to recover (regardless + %% of success or not) otherwise later testcases + %% may unnecessarily fail. + ?t:timetrap_cancel(Dog), + receive after SleepSecs+500 -> ok end + end; + _ -> ?line {skip, "Not implemented for this OS"} + end. + +exit_status_msb_test(Config, SleepSecs) when is_list(Config) -> + %% + %% We want to start port programs from as many schedulers as possible + %% and we want these port programs to terminate while multi-scheduling + %% is blocked. + %% + ?line NoSchedsOnln = erlang:system_info(schedulers_online), + ?line Parent = self(), + ?line ?t:format("SleepSecs = ~p~n", [SleepSecs]), + ?line PortProg = "sleep " ++ integer_to_list(SleepSecs), + ?line Start = now(), + ?line NoProcs = case NoSchedsOnln of + NProcs when NProcs < ?EXIT_STATUS_MSB_MAX_PROCS -> + NProcs; + _ -> + ?EXIT_STATUS_MSB_MAX_PROCS + end, + ?line NoPortsPerProc = case 20*NoProcs of + TNPorts when TNPorts < ?EXIT_STATUS_MSB_MAX_PORTS -> 20; + _ -> ?EXIT_STATUS_MSB_MAX_PORTS div NoProcs + end, + ?line ?t:format("NoProcs = ~p~nNoPortsPerProc = ~p~n", + [NoProcs, NoPortsPerProc]), + ProcFun + = fun () -> + PrtSIds = lists:map( + fun (_) -> + erlang:yield(), + case catch open_port({spawn, PortProg}, + [exit_status]) of + Prt when is_port(Prt) -> + {Prt, + erlang:system_info(scheduler_id)}; + {'EXIT', {Err, _}} when Err == eagain; + Err == emfile -> + noop; + {'EXIT', Err} when Err == eagain; + Err == emfile -> + noop; + Error -> + ?t:fail(Error) + end + end, + lists:seq(1, NoPortsPerProc)), + SIds = lists:filter(fun (noop) -> false; + (_) -> true + end, + lists:map(fun (noop) -> noop; + ({_, SId}) -> SId + end, + PrtSIds)), + process_flag(scheduler, 0), + Parent ! {self(), started, SIds}, + lists:foreach( + fun (noop) -> + noop; + ({Port, _}) -> + receive + {Port, {exit_status, 0}} -> + ok; + {Port, {exit_status, Status}} when Status > 128 -> + %% Sometimes happens when we have created + %% too many ports. + ok; + {Port, {exit_status, _}} = ESMsg -> + {Port, {exit_status, 0}} = ESMsg + end + end, + PrtSIds), + Parent ! {self(), done} + end, + ?line Procs = lists:map(fun (N) -> + spawn_opt(ProcFun, + [link, + {scheduler, + (N rem NoSchedsOnln)+1}]) + end, + lists:seq(1, NoProcs)), + ?line SIds = lists:map(fun (P) -> + receive {P, started, SIds} -> SIds end + end, + Procs), + ?line StartedTime = timer:now_diff(now(), Start)/1000000, + ?line ?t:format("StartedTime = ~p~n", [StartedTime]), + ?line true = StartedTime < SleepSecs, + ?line erlang:system_flag(multi_scheduling, block), + ?line lists:foreach(fun (P) -> receive {P, done} -> ok end end, Procs), + ?line DoneTime = timer:now_diff(now(), Start)/1000000, + ?line ?t:format("DoneTime = ~p~n", [DoneTime]), + ?line true = DoneTime > SleepSecs, + ?line ok = verify_multi_scheduling_blocked(), + ?line erlang:system_flag(multi_scheduling, unblock), + ?line case {length(lists:usort(lists:flatten(SIds))), NoSchedsOnln} of + {N, N} -> + ?line ok; + {N, M} -> + ?line ?t:fail("Failed to create ports on all" + ++ integer_to_list(M) ++ " available" + "schedulers. Only created ports on " + ++ integer_to_list(N) ++ " schedulers.") + end. + +save_sid(SIds) -> + SId = erlang:system_info(scheduler_id), + case lists:member(SId, SIds) of + true -> SIds; + false -> [SId|SIds] + end. + +sid_proc(SIds) -> + NewSIds = save_sid(SIds), + receive + {From, want_sids} -> + From ! {self(), sids, NewSIds} + after 0 -> + sid_proc(NewSIds) + end. + +verify_multi_scheduling_blocked() -> + ?line Procs = lists:map(fun (_) -> + spawn_link(fun () -> sid_proc([]) end) + end, + lists:seq(1, 3*erlang:system_info(schedulers_online))), + ?line receive after 1000 -> ok end, + ?line SIds = lists:map(fun (P) -> + P ! {self(), want_sids}, + receive {P, sids, PSIds} -> PSIds end + end, + Procs), + ?line 1 = length(lists:usort(lists:flatten(SIds))), + ?line ok. + + +%%% Pinging functions. + +stream_ping(Config, Size, CmdLine, Options) -> + Data = random_packet(Size), + port_expect(Config, [{Data, [Data]}], 0, CmdLine, Options). + +ping(Config, Sizes, HSize, CmdLine, Options) -> + Actions = lists:map(fun(Size) -> + [$p|Packet] = random_packet(Size, "ping"), + {[$p|Packet], [[$P|Packet]]} + end, + Sizes), + port_expect(Config, Actions, HSize, CmdLine, Options). + +%% expect_input(Sizes, HSize, CmdLine, Options) +%% +%% Sizes = Size of packets to generated. +%% HSize = Header size: 1, 2, or 4 +%% CmdLine = Additional command line options. +%% Options = Addtional port options. + +expect_input(Config, Sizes, HSize, CmdLine, Options) -> + expect_input1(Config, Sizes, {HSize, CmdLine, Options}, [], []). + +expect_input1(Config, [0|Rest], Params, Expect, ReplyCommand) -> + expect_input1(Config, Rest, Params, [""|Expect], ["x0"|ReplyCommand]); +expect_input1(Config, [Size|Rest], Params, Expect, ReplyCommand) -> + Packet = random_packet(Size), + Fmt = io_lib:format("~c~p", [hd(Packet), Size]), + expect_input1(Config, Rest, Params, [Packet|Expect], [Fmt|ReplyCommand]); +expect_input1(Config, [], {HSize, CmdLine0, Options}, Expect, ReplyCommand) -> + CmdLine = build_cmd_line(CmdLine0, ReplyCommand, []), + port_expect(Config, [{false, lists:reverse(Expect)}], + HSize, CmdLine, Options). + +build_cmd_line(FixedCmdLine, [Cmd|Rest], []) -> + build_cmd_line(FixedCmdLine, Rest, [Cmd]); +build_cmd_line(FixedCmdLine, [Cmd|Rest], Result) -> + build_cmd_line(FixedCmdLine, Rest, [Cmd, $:|Result]); +build_cmd_line(FixedCmdLine, [], Result) -> + lists:flatten([FixedCmdLine, " -r", Result, " -n"]). + +%% port_expect(Actions, HSize, CmdLine, Options) +%% +%% Actions = [{Send, ExpectList}|Rest] +%% HSize = 0 (stream), or 1, 2, 4 (header size aka "packet bytes") +%% CmdLine = Command line for port_test. Don't include -h<digit>. +%% Options = Options for open_port/2. Don't include {packet, Number} or +%% or stream. +%% +%% Send = false | list() +%% ExpectList = List of lists or binaries. +%% +%% Returns the port. + +port_expect(Config, Actions, HSize, CmdLine, Options0) -> +% io:format("port_expect(~p, ~p, ~p, ~p)", +% [Actions, HSize, CmdLine, Options0]), + ?line PortTest = port_test(Config), + ?line Cmd = lists:concat([PortTest, " -h", HSize, " ", CmdLine]), + ?line PortType = + case HSize of + 0 -> stream; + _ -> {packet, HSize} + end, + ?line Options = [PortType|Options0], + ?line io:format("open_port({spawn, ~p}, ~p)", [Cmd, Options]), + ?line Port = open_port({spawn, Cmd}, Options), + ?line port_expect(Port, Actions, Options), + Port. + +port_expect(Port, [{Send, Expects}|Rest], Options) when is_list(Expects) -> + ?line port_send(Port, Send), + ?line IsBinaryPort = lists:member(binary, Options), + ?line Receiver = + case {lists:member(stream, Options), line_option(Options)} of + {false, _} -> fun receive_all/2; + {true,false} -> fun stream_receive_all/2; + {_, true} -> fun receive_all/2 + end, + ?line Receiver(Port, maybe_to_binary(Expects, IsBinaryPort)), + ?line port_expect(Port, Rest, Options); +port_expect(_, [], _) -> + ok. + +%%% Check for either line or {line,N} in option list +line_option([{line,_}|_]) -> + true; +line_option([line|_]) -> + true; +line_option([_|T]) -> + line_option(T); +line_option([]) -> + false. + +any_list_to_binary({Atom, List}) -> + {Atom, list_to_binary(List)}; +any_list_to_binary(List) -> + list_to_binary(List). + +maybe_to_binary(Expects, true) -> + lists:map(fun any_list_to_binary/1, Expects); +maybe_to_binary(Expects, false) -> + Expects. + +port_send(_Port, false) -> ok; +port_send(Port, Send) when is_list(Send) -> +% io:format("port_send(~p, ~p)", [Port, Send]), + Port ! {self(), {command, Send}}. + +receive_all(Port, [Expect|Rest]) -> +% io:format("receive_all(~p, [~p|Rest])", [Port, Expect]), + receive + {Port, {data, Expect}} -> + io:format("Received ~s", [format(Expect)]), + ok; + {Port, {data, Other}} -> + io:format("Received ~s; expected ~s", + [format(Other), format(Expect)]), + test_server:fail(bad_message); + Other -> + %% (We're not yet prepared for receiving both 'eol' and + %% 'exit_status'; remember that they may appear in any order.) + case {Expect, Rest, Other} of + {eof, [], {Port, eof}} -> + io:format("Received soft EOF.",[]), + ok; + {{exit_status, S}, [], {Port, {exit_status, S}}} -> + io:format("Received exit status ~p.",[S]), + ok; + _ -> +%%% io:format("Unexpected message: ~s", [format(Other)]), + io:format("Unexpected message: ~w", [Other]), + ?line test_server:fail(unexpected_message) + end + end, + receive_all(Port, Rest); +receive_all(_Port, []) -> + ok. + +stream_receive_all(Port, [Expect]) -> + stream_receive_all1(Port, Expect). + +stream_receive_all1(_Port, Empty) when is_binary(Empty), size(Empty) == 0 -> + ok; +stream_receive_all1(_Port, []) -> + ok; +stream_receive_all1(Port, Expect) -> + receive + {Port, {data, Data}} -> + Remaining = compare(Data, Expect), + stream_receive_all1(Port, Remaining); + Other -> + test_server:fail({bad_message, Other}) + end. + +compare(B1, B2) when is_binary(B1), is_binary(B2), byte_size(B1) =< byte_size(B2) -> + case split_binary(B2, size(B1)) of + {B1,Remaining} -> + Remaining; + _Other -> + test_server:fail(nomatch) + end; +compare(B1, B2) when is_binary(B1), is_binary(B2) -> + test_server:fail(too_much_data); +compare([X|Rest1], [X|Rest2]) -> + compare(Rest1, Rest2); +compare([_|_], [_|_]) -> + test_server:fail(nomatch); +compare([], Remaining) -> + Remaining; +compare(_Data, []) -> + test_server:fail(too_much_data). + +maybe_to_list(Bin) when is_binary(Bin) -> + binary_to_list(Bin); +maybe_to_list(List) -> + List. + +format({Eol,List}) -> + io_lib:format("tuple<~w,~s>",[Eol, maybe_to_list(List)]); +format(List) when is_list(List) -> + case list_at_least(50, List) of + true -> + io_lib:format("\"~-50s...\"", [List]); + false -> + io_lib:format("~p", [List]) + end; +format(Bin) when is_binary(Bin), size(Bin) >= 50 -> + io_lib:format("binary<~-50s...>", [binary_to_list(Bin, 1, 50)]); +format(Bin) when is_binary(Bin) -> + io_lib:format("binary<~s>", [binary_to_list(Bin)]). + + +list_at_least(Number, [_|Rest]) when Number > 0 -> + list_at_least(Number-1, Rest); +list_at_least(Number, []) when Number > 0 -> + false; +list_at_least(0, _List) -> true. + + +%%% Utility functions. + +random_packet(Size) -> + random_packet(Size, ""). + +random_packet(Size, Prefix) -> + build_packet(Size-length(Prefix), lists:reverse(Prefix), random_char()). + +build_packet(0, Result, _NextChar) -> + lists:reverse(Result); +build_packet(Left, Result, NextChar0) -> + NextChar = + if + NextChar0 >= 126 -> + 33; + true -> + NextChar0+1 + end, + build_packet(Left-1, [NextChar0|Result], NextChar). + +sizes() -> + case os:type() of + vxworks -> + % don't stress VxWorks too much + [10, 13, 64, 127, 128, 255, 256, 1023, 1024, + 8191, 8192, 16383, 16384]; + _ -> + [10, 13, 64, 127, 128, 255, 256, 1023, 1024, + 32767, 32768, 65535, 65536] + end. + +sizes(Header_Size) -> + sizes(Header_Size, sizes(), []). + +sizes(1, [Packet_Size|Rest], Result) when Packet_Size < 256 -> + sizes(1, Rest, [Packet_Size|Result]); +sizes(2, [Packet_Size|Rest], Result) when Packet_Size < 65536 -> + sizes(2, Rest, [Packet_Size|Result]); +sizes(4, [Packet_Size|Rest], Result) -> + sizes(4, Rest, [Packet_Size|Result]); +sizes(_, _, Result) -> + Result. + +random_char() -> + random_char("abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ0123456789"). + +random_char(Chars) -> + lists:nth(uniform(length(Chars)), Chars). + +uniform(N) -> + case get(random_seed) of + undefined -> + {X, Y, Z} = Seed = time(), + io:format("Random seed = ~p\n",[Seed]), + random:seed(X, Y, Z); + _ -> + ok + end, + random:uniform(N). + +fun_spawn(Fun) -> + fun_spawn(Fun, []). + +fun_spawn(Fun, Args) -> + spawn_link(erlang, apply, [Fun, Args]). + +port_test(Config) when is_list(Config) -> + ?line filename:join(?config(data_dir, Config), "port_test"). + + +ports(doc) -> "Test that erlang:ports/0 returns a consistent snapshot of ports"; +ports(suite) -> []; +ports(Config) when is_list(Config) -> + ?line Path = ?config(data_dir, Config), + ?line ok = load_driver(Path, "exit_drv"), + + receive after 1000 -> ok end, % Wait for other ports to stabilize + + ?line OtherPorts = erlang:ports(), + io:format("Other ports: ~p\n",[OtherPorts]), + MaxPorts = 1024 - length(OtherPorts), + + TrafficPid = spawn_link(fun() -> ports_traffic(MaxPorts) end), + + ports_snapshots(100, TrafficPid, OtherPorts), + TrafficPid ! {self(),die}, + ?line receive {TrafficPid, dead} -> ok end, + ok. + +ports_snapshots(0, _, _) -> + ok; +ports_snapshots(Iter, TrafficPid, OtherPorts) -> + + TrafficPid ! start, + ?line receive after 1 -> ok end, + + Snapshot = erlang:ports(), + + TrafficPid ! {self(), stop}, + ?line receive {TrafficPid, EventList, TrafficPorts} -> ok end, + + %%io:format("Snapshot=~p\n", [Snapshot]), + ports_verify(Snapshot, OtherPorts ++ TrafficPorts, EventList), + + ports_snapshots(Iter-1, TrafficPid, OtherPorts). + + +ports_traffic(MaxPorts) -> + ports_traffic_stopped(MaxPorts, {[],0}). + +ports_traffic_stopped(MaxPorts, {PortList, PortCnt}) -> + receive + start -> + %%io:format("Traffic started in ~p\n",[self()]), + ports_traffic_started(MaxPorts, {PortList, PortCnt}, []); + {Pid,die} -> + ?line lists:foreach(fun(Port)-> erlang:port_close(Port) end, + PortList), + Pid ! {self(),dead} + end. + +ports_traffic_started(MaxPorts, {PortList, PortCnt}, EventList) -> + receive + {Pid, stop} -> + %%io:format("Traffic stopped in ~p\n",[self()]), + Pid ! {self(), EventList, PortList}, + ports_traffic_stopped(MaxPorts, {PortList, PortCnt}) + + after 0 -> + ports_traffic_do(MaxPorts, {PortList, PortCnt}, EventList) + end. + +ports_traffic_do(MaxPorts, {PortList, PortCnt}, EventList) -> + N = uniform(MaxPorts), + case N > PortCnt of + true -> % Open port + ?line P = open_port({spawn, "exit_drv"}, []), + %%io:format("Created port ~p\n",[P]), + ports_traffic_started(MaxPorts, {[P|PortList], PortCnt+1}, + [{open,P}|EventList]); + + false -> % Close port + ?line P = lists:nth(N, PortList), + %%io:format("Close port ~p\n",[P]), + ?line true = erlang:port_close(P), + ports_traffic_started(MaxPorts, {lists:delete(P,PortList), PortCnt-1}, + [{close,P}|EventList]) + end. + +ports_verify(Ports, PortsAfter, EventList) -> + %%io:format("Candidate=~p\nEvents=~p\n", [PortsAfter, EventList]), + case lists:sort(Ports) =:= lists:sort(PortsAfter) of + true -> + io:format("Snapshot of ~p ports verified ok.\n",[length(Ports)]), + ok; + false -> + %% Note that we track the event list "backwards", undoing open/close: + case EventList of + [{open,P} | Tail] -> + ports_verify(Ports, lists:delete(P,PortsAfter), Tail); + + [{close,P} | Tail] -> + ports_verify(Ports, [P | PortsAfter], Tail); + + [] -> + ?line test_server:fail("Inconsistent snapshot from erlang:ports()") + end + end. + +load_driver(Dir, Driver) -> + case erl_ddll:load_driver(Dir, Driver) of + ok -> ok; + {error, Error} = Res -> + io:format("~s\n", [erl_ddll:format_error(Error)]), + Res + end. diff --git a/erts/emulator/test/port_SUITE_data/Makefile.src b/erts/emulator/test/port_SUITE_data/Makefile.src new file mode 100644 index 0000000000..d97b37c9ae --- /dev/null +++ b/erts/emulator/test/port_SUITE_data/Makefile.src @@ -0,0 +1,26 @@ +CC = @CC@ +LD = @LD@ +CFLAGS = @CFLAGS@ -I@erl_include@ @DEFS@ +CROSSLDFLAGS = @CROSSLDFLAGS@ + +PROGS = port_test@exe@ echo_args@exe@ +DRIVERS = echo_drv@dll@ exit_drv@dll@ failure_drv@dll@ + +all: $(PROGS) $(DRIVERS) port_test.@EMULATOR@ + +port_test@exe@: port_test@obj@ + $(LD) $(CROSSLDFLAGS) -o port_test port_test@obj@ @LIBS@ + +port_test@obj@: port_test.c + $(CC) -c -o port_test@obj@ $(CFLAGS) port_test.c + +echo_args@exe@: echo_args@obj@ + $(LD) $(CROSSLDFLAGS) -o echo_args echo_args@obj@ @LIBS@ + +echo_args@obj@: echo_args.c + $(CC) -c -o echo_args@obj@ $(CFLAGS) echo_args.c + +port_test.@EMULATOR@: port_test.erl + @erl_name@ -compile port_test + +@SHLIB_RULES@ diff --git a/erts/emulator/test/port_SUITE_data/dir/dummy b/erts/emulator/test/port_SUITE_data/dir/dummy new file mode 100644 index 0000000000..442071915b --- /dev/null +++ b/erts/emulator/test/port_SUITE_data/dir/dummy @@ -0,0 +1 @@ +Dumma WinZip!! diff --git a/erts/emulator/test/port_SUITE_data/echo_args.c b/erts/emulator/test/port_SUITE_data/echo_args.c new file mode 100644 index 0000000000..91dca8993f --- /dev/null +++ b/erts/emulator/test/port_SUITE_data/echo_args.c @@ -0,0 +1,12 @@ +#include <stdio.h> + +int main(int argc, char **argv) +{ + int i; + + for(i = 0; i < argc; ++i) { + printf("argv[%d]:|%s|\n",i,argv[i]); + } + return 0; +} + diff --git a/erts/emulator/test/port_SUITE_data/echo_drv.c b/erts/emulator/test/port_SUITE_data/echo_drv.c new file mode 100644 index 0000000000..25eda116fe --- /dev/null +++ b/erts/emulator/test/port_SUITE_data/echo_drv.c @@ -0,0 +1,85 @@ +#include <stdio.h> +#include "erl_driver.h" + + + +/* ------------------------------------------------------------------------- +** Data types +**/ + +typedef struct _erl_drv_data EchoDrvData; + + + +/* ------------------------------------------------------------------------- +** Entry struct +**/ + +static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command); +static void echo_drv_stop(EchoDrvData *data_p); +static void echo_drv_output(EchoDrvData *data_p, char *buf, int len); +static void echo_drv_finish(void); +static int echo_drv_control(EchoDrvData *data_p, unsigned int command, + char *buf, int len, + char **rbuf, int rlen); + +static ErlDrvEntry echo_drv_entry = { + NULL, /* init */ + echo_drv_start, + echo_drv_stop, + echo_drv_output, + NULL, /* ready_input */ + NULL, /* ready_output */ + "echo_drv", + echo_drv_finish, + NULL, /* handle */ + echo_drv_control, + NULL, /* timeout */ + NULL, /* outputv */ + NULL /* ready_async */ +}; + + + +/* ------------------------------------------------------------------------- +** Entry functions +**/ + +DRIVER_INIT(echo_drv) +{ + return &echo_drv_entry; +} + +static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command) { + void *void_ptr; + int res = -4711; + if (command) { + while(*command != '\0' && *command != ' ') + ++command; + while(*command != '\0' && *command == ' ') + ++command; + if(*command == '-') { + res = driver_output(port, command+1, strlen(command) - 1); + } + } + return void_ptr = port; +} + +static void echo_drv_stop(EchoDrvData *data_p) { +} + +static void echo_drv_output(EchoDrvData *data_p, char *buf, int len) { + void *void_ptr; + ErlDrvPort port = void_ptr = data_p; + + driver_output(port, buf, len); +} + +static void echo_drv_finish() { +} + +static int echo_drv_control(EchoDrvData *data_p, unsigned int command, + char *buf, int len, + char **rbuf, int rlen) { + return 0; +} diff --git a/erts/emulator/test/port_SUITE_data/exit_drv.c b/erts/emulator/test/port_SUITE_data/exit_drv.c new file mode 100644 index 0000000000..60f1b321bd --- /dev/null +++ b/erts/emulator/test/port_SUITE_data/exit_drv.c @@ -0,0 +1,68 @@ +#include <stdlib.h> +#include "erl_driver.h" + +typedef struct _erl_drv_data ExitDrvData; + +static ExitDrvData *exit_drv_start(ErlDrvPort port, char *command); +static void exit_drv_stop(ExitDrvData *data_p); +static void exit_drv_output(ExitDrvData *data_p, char *buf, int len); +static void exit_drv_finish(void); +static int exit_drv_control(ExitDrvData *data_p, unsigned int command, + char *buf, int len, + char **rbuf, int rlen); + +static ErlDrvEntry exit_drv_entry = { + NULL, /* init */ + exit_drv_start, + exit_drv_stop, + exit_drv_output, + NULL, /* ready_input */ + NULL, /* ready_output */ + "exit_drv", + exit_drv_finish, + NULL, /* handle */ + exit_drv_control, + NULL, /* timeout */ + NULL, /* outputv */ + NULL /* ready_async */ +}; + +DRIVER_INIT(exit_drv) +{ + return &exit_drv_entry; +} + +static ExitDrvData * +exit_drv_start(ErlDrvPort port, char *command) +{ + return (ExitDrvData *) port; +} + +static void +exit_drv_stop(ExitDrvData *datap) +{ + +} + +static void +exit_drv_output(ExitDrvData *datap, char *buf, int len) +{ + driver_exit((ErlDrvPort) datap, 0); +} + +static void +exit_drv_finish(void) +{ + +} + +static int +exit_drv_control(ExitDrvData *datap, + unsigned int command, + char *buf, + int len, + char **rbuf, + int rlen) +{ + return 0; +} diff --git a/erts/emulator/test/port_SUITE_data/failure_drv.c b/erts/emulator/test/port_SUITE_data/failure_drv.c new file mode 100644 index 0000000000..34d48e00f8 --- /dev/null +++ b/erts/emulator/test/port_SUITE_data/failure_drv.c @@ -0,0 +1,63 @@ +#include <stdio.h> +#include "erl_driver.h" + +typedef struct _erl_drv_data FailureDrvData; + +static FailureDrvData *failure_drv_start(ErlDrvPort, char *); +static void failure_drv_stop(FailureDrvData *); +static void failure_drv_output(FailureDrvData *, char *, int); +static void failure_drv_finish(void); +static int failure_drv_control(FailureDrvData *, unsigned int, + char *, int, char **, int); + +static ErlDrvEntry failure_drv_entry = { + NULL, /* init */ + failure_drv_start, + failure_drv_stop, + failure_drv_output, + NULL, /* ready_input */ + NULL, /* ready_output */ + "failure_drv", + failure_drv_finish, + NULL, /* handle */ + failure_drv_control, + NULL, /* timeout */ + NULL, /* outputv */ + NULL /* ready_async */ +}; + + + +/* ------------------------------------------------------------------------- +** Entry functions +**/ + +DRIVER_INIT(failure_drv) +{ + return &failure_drv_entry; +} + +static FailureDrvData *failure_drv_start(ErlDrvPort port, char *command) { + void *void_ptr; + + return void_ptr = port; +} + +static void failure_drv_stop(FailureDrvData *data_p) { +} + +static void failure_drv_output(FailureDrvData *data_p, char *buf, int len) { + void *void_ptr; + ErlDrvPort port = void_ptr = data_p; + + driver_failure_atom(port, "driver_failed"); +} + +static void failure_drv_finish() { +} + +static int failure_drv_control(FailureDrvData *data_p, unsigned int command, + char *buf, int len, + char **rbuf, int rlen) { + return 0; +} diff --git a/erts/emulator/test/port_SUITE_data/port_test.c b/erts/emulator/test/port_SUITE_data/port_test.c new file mode 100644 index 0000000000..7b4e386d87 --- /dev/null +++ b/erts/emulator/test/port_SUITE_data/port_test.c @@ -0,0 +1,605 @@ +/* + * Author: Bjorn Gustavsson + * Purpose: A port program to be used for testing the open_port bif. + */ + +#ifdef VXWORKS +#include <vxWorks.h> +#include <taskVarLib.h> +#include <taskLib.h> +#include <sysLib.h> +#include <string.h> +#include <ioLib.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#ifndef __WIN32__ +#include <unistd.h> + +#ifdef VXWORKS +#include "reclaim.h" +#include <sys/times.h> +#else +#include <sys/time.h> +#endif + +#define O_BINARY 0 +#define _setmode(fd, mode) +#endif + +#ifdef __WIN32__ +#include "windows.h" +#include "winbase.h" +#endif + + +#ifdef VXWORKS +#define REDIR_STDOUT(fd) ioTaskStdSet(0, 1, fd); +#else +#define REDIR_STDOUT(fd) if (dup2(fd, 1) == -1) { \ + fprintf(stderr, "%s: failed to duplicate handle %d to 1: %d\n", \ + port_data->progname, fd, errno); \ + exit(1); \ +} +#endif + +#ifdef VXWORKS +#define MAIN(argc, argv) port_test(argc, argv) +#else +#define MAIN(argc, argv) main(argc, argv) +#endif + + +extern int errno; + +typedef struct { + char* progname; /* Name of this program (from argv[0]). */ + int header_size; /* Number of bytes in each packet header: + * 1, 2, or 4, or 0 for a continous byte stream. */ + int fd_from_erl; /* File descriptor from Erlang. */ + int fd_to_erl; /* File descriptor to Erlang. */ + unsigned char* io_buf; /* Buffer for file i/o. */ + int io_buf_size; /* Current size of i/o buffer. */ + int delay_mode; /* If set, this program will wait 5 seconds + * after reading the header for a packet + * before reading the rest. + */ + int break_mode; /* If set, this program will close standard + * input, which should case broken pipe + * error in the writer. + */ + int quit_mode; /* If set, this program will exit + * just after reading the packet header. + */ + int slow_writes; /* Writes back the reply in chunks with + * sleeps in between. The value is the + * chunk size. If 0, normal writes are done. + */ + char* output_file; /* File into which the result will be written. */ + int no_packet_loop; /* No packet loop. */ + + int limited_bytecount; /* Only answer a limited number of bytes, then exit (stream mode) */ + +} PORT_TEST_DATA; + +PORT_TEST_DATA* port_data; + +static int packet_loop(); +static void reply(); +static void write_reply(); +static void ensure_buf_big_enough(); +static int readn(); +static void delay(unsigned ms); +static void dump(unsigned char* buf, int sz, int max); +static void replace_stdout(char* filename); +static void generate_reply(char* spec); + +#ifndef VXWORKS +#ifndef HAVE_STRERROR +extern int sys_nerr; +#ifndef sys_errlist /* sys_errlist is sometimes defined to + call a function on win32 */ +extern char *sys_errlist[]; +#endif + +char* +strerror(err) +int err; +{ + static char msgstr[1024]; + + if (err == 0) { + msgstr[0] = '\0'; + } else if (0 < err && err < sys_nerr) { + strcpy(msgstr, sys_errlist[err]); + } else { + sprintf(msgstr, "Unknown error %d", err); + } + return msgstr; +} +#endif +#endif + + +MAIN(argc, argv) +int argc; +char *argv[]; +{ + int ret; +#ifdef VXWORKS + if(taskVarAdd(0, (int *)&port_data) != OK) { + fprintf(stderr, "Can't do taskVarAdd in port_test\n"); + exit(1); + } +#endif + if((port_data = (PORT_TEST_DATA *) malloc(sizeof(PORT_TEST_DATA))) == NULL) { + fprintf(stderr, "Couldn't malloc for port_data"); + exit(1); + } + port_data->header_size = 0; + port_data->io_buf_size = 0; + port_data->delay_mode = 0; + port_data->break_mode = 0; + port_data->quit_mode = 0; + port_data->slow_writes = 0; + port_data->output_file = NULL; + port_data->no_packet_loop = 0; + + port_data->progname = argv[0]; + port_data->fd_from_erl = 0; + port_data->fd_to_erl = 1; + + port_data->limited_bytecount = 0; + + _setmode(0, _O_BINARY); + _setmode(1, _O_BINARY); + + while (argc > 1 && argv[1][0] == '-') { + switch (argv[1][1]) { + case 'b': /* Break mode. */ + port_data->break_mode = 1; + break; + case 'c': /* Close standard output. */ + close(port_data->fd_to_erl); + break; + case 'd': /* Delay mode. */ + port_data->delay_mode = 1; + break; + case 'e': + port_data->fd_to_erl = 2; + break; + case 'h': /* Header size for packets. */ + switch (argv[1][2]) { + case '0': port_data->header_size = 0; break; + case '1': port_data->header_size = 1; break; + case '2': port_data->header_size = 2; break; + case '4': port_data->header_size = 4; break; + case '\0': + fprintf(stderr, "%s: missing header size for -h\n", port_data->progname); + return 1; + default: + fprintf(stderr, "%s: illegal packet header size: %c\n", + port_data->progname, argv[1][2]); + return 1; + } + break; + case 'l': + port_data->limited_bytecount = atoi(argv[1]+2); + break; + case 'n': /* No packet loop. */ + port_data->no_packet_loop = 1; + break; + case 'o': /* Output to file. */ + port_data->output_file = argv[1]+2; + break; + case 'q': /* Quit mode. */ + port_data->quit_mode = 1; + break; + case 'r': /* Generate reply. */ + generate_reply(argv[1]+2); + break; + case 's': /* Slow writes. */ + port_data->slow_writes = atoi(argv[1]+2); + break; + default: + fprintf(stderr, "Unrecognized switch: %s\n", argv[1]); + free(port_data); + exit(1); + } + argc--, argv++; + } + + if (argc > 1) { + /* XXX Add error printout here */ + } + + if (port_data->no_packet_loop){ + free(port_data); + exit(0); + } + + /* + * If an output file was given, let it replace standard output. + */ + + if (port_data->output_file) + replace_stdout(port_data->output_file); + + ret = packet_loop(); + if(port_data->io_buf_size > 0) + free(port_data->io_buf); + free(port_data); + return ret; +} + +static int +packet_loop(void) +{ + int total_read = 0; + port_data->io_buf = (unsigned char*) malloc(1); /* Allocate once, so realloc works (SunOS) */ + + + for (;;) { + int packet_length; /* Length of current packet. */ + int i; + int bytes_read; /* Number of bytes read. */ + + /* + * Read the packet header, if any. + */ + + if (port_data->header_size == 0) { + if(port_data->limited_bytecount && + port_data->limited_bytecount - total_read < 4096) + packet_length = port_data->limited_bytecount - total_read; + else + packet_length = 4096; + } else { + ensure_buf_big_enough(port_data->header_size); + if (readn(port_data->fd_from_erl, port_data->io_buf, port_data->header_size) != port_data->header_size) { + return(1); + } + + /* + * Get the length of this packet. + */ + + packet_length = 0; + for (i = 0; i < port_data->header_size; i++) + packet_length = (packet_length << 8) | port_data->io_buf[i]; + } + + + /* + * Delay if delay mode. + */ + + if (port_data->delay_mode) { + delay(5000L); + } + + if (port_data->quit_mode) { + return(1); + } else if (port_data->break_mode) { + close(0); + delay(32000L); + return(1); + } + + /* + * Read the packet itself. + */ + + ensure_buf_big_enough(packet_length+4+1); /* At least five bytes. */ + port_data->io_buf[4] = '\0'; + if (port_data->header_size == 0) { + bytes_read = read(port_data->fd_from_erl, port_data->io_buf+4, packet_length); + if (bytes_read == 0) + return(1); + if (bytes_read < 0) { + fprintf(stderr, "Error reading %d bytes: %s\n", + packet_length, strerror(errno)); + return(1); + } + total_read += bytes_read; + } else { + bytes_read = readn(port_data->fd_from_erl, port_data->io_buf+4, packet_length); + if (bytes_read != packet_length) { + fprintf(stderr, "%s: couldn't read packet of length %d\r\n", + port_data->progname, packet_length); + return(1); + } + } + + /* + * Act on the command. + */ + if (port_data->header_size == 0) { + reply(port_data->io_buf+4, bytes_read); + if(port_data->limited_bytecount && + port_data->limited_bytecount <= total_read){ + delay(5000L); + return(0); + } + } else { + switch (port_data->io_buf[4]) { + case 'p': /* ping */ + port_data->io_buf[4] = 'P'; + reply(port_data->io_buf+4, bytes_read); + break; + case 'e': /* echo */ + reply(port_data->io_buf+4, bytes_read); + break; + case 'x': /* exit */ + return(5); + break; + default: + fprintf(stderr, "%s: bad packet of length %d received: ", + port_data->progname, bytes_read); + dump(port_data->io_buf+4, bytes_read, 10); + fprintf(stderr, "\r\n"); + return(1); + } + } + } +} + +/* + * Sends a packet back to Erlang. + */ + +static void +reply(buf, size) + char* buf; /* Buffer with reply. The four bytes before + * this pointer must be allocated so that + * this function can put the header there. + */ + int size; /* Size of buffer to send. */ +{ + int n; /* Temporary to hold size. */ + int i; /* Loop counter. */ + + /* + * Fill the header starting with the least significant byte + * (this will work even if there is no header). + */ + + n = size; + for (i = 0; i < port_data->header_size; i++) { + *--buf = (char) n; /* Store least significant byte. */ + n = n >> 8; + } + + size += port_data->header_size; + write_reply(buf, size); +} + + + +static void +write_reply(buf, size) + char* buf; /* Buffer with reply. Must contain header. */ + int size; /* Size of buffer to send. */ +{ + int n; /* Temporary to hold size. */ + + if (port_data->slow_writes <= 0) { /* Normal, "fast", write. */ + write(port_data->fd_to_erl, buf, size); + } else { + /* + * Write chunks with delays in between. + */ + + while (size > 0) { + n = size > port_data->slow_writes ? port_data->slow_writes : size; + write(port_data->fd_to_erl, buf, n); + size -= n; + buf += n; + if (size) + delay(500L); + } + } +} + + +/* + * Ensures that our I/O buffer is big enough for the packet to come. + */ + +static void +ensure_buf_big_enough(size) + int size; /* Needed size of buffer. */ +{ + if (port_data->io_buf_size >= size) + return; + + port_data->io_buf = (unsigned char*) realloc(port_data->io_buf, size); + if (port_data->io_buf == NULL) { + fprintf(stderr, "%s: insufficient memory for i/o buffer of size %d\n", + port_data->progname, size); + exit(1); + } + port_data->io_buf_size = size; +} + +/* + * Reads len number of bytes. + */ +static int +readn(fd, buf, len) + int fd; /* File descriptor to read from. */ + unsigned char *buf; /* Store in this buffer. */ + int len; /* Number of bytes to read. */ +{ + int n; /* Byte count in last read call. */ + int sofar; /* Bytes read so far. */ + + sofar = 0; + do { + if ((n = read(fd, buf+sofar, len-sofar)) <= 0) + /* error or EOF in read */ + return(n); + sofar += n; + } while (sofar < len); + return sofar; +} + +static void +replace_stdout(filename) +char* filename; /* Name of file to replace standard output. */ +{ + int fd; + + fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0666); + if (fd == -1) { + fprintf(stderr, "%s: failed to open %s for writing: %d\n", + port_data->progname, filename, errno); + exit(1); + } + REDIR_STDOUT(fd); +} + +static void +dump(buf, sz, max) + unsigned char* buf; + int sz; + int max; +{ + int i, imax; + char comma[5]; + + comma[0] = ','; + comma[1] = '\0'; + if (!sz) + return; + if (sz > max) + imax = max; + else + imax = sz; + + for (i=0; i<imax; i++) { + if (i == imax-1) { + if (sz > max) + strcpy(comma, ",..."); + else + comma[0] = 0; + } + if (isdigit(buf[i])) { + fprintf(stderr, "%u%s", (int)(buf[i]), comma); + } else { + if (isalpha(buf[i])) { + fprintf(stderr, "%c%s", buf[i], comma); + } + else { + fprintf(stderr, "%u%s", (int)(buf[i]), comma); + } + } + } +} + +/* + * Delays (sleeps) the given number of milli-seconds. + */ + +static void +delay(unsigned ms) +{ +#ifdef VXWORKS + taskDelay((sysClkRateGet() * ms) / 1000); +#else +#ifdef __WIN32__ + Sleep(ms); +#else + struct timeval t; + t.tv_sec = ms/1000; + t.tv_usec = (ms % 1000) * 1000; + + select(0, NULL, NULL, NULL, &t); +#endif +#endif +} + +/* + * Generates a reply buffer given the specification. + * + * <packet-bytes>,<start-character>,<increment>,<size> + * + * Where: + * <packet-bytes> is + */ +static void +generate_reply(spec) +char* spec; /* Specification for reply. */ +{ + typedef struct item { + int start; /* Start character. */ + int incrementer; /* How much to increment. */ + size_t size; /* Size of reply buffer. */ + } Item; + + Item items[256]; + int last; + int cur; + size_t total_size; + char* buf; /* Reply buffer. */ + char* s; /* Current pointer into buffer. */ + int c; + + total_size = 0; + last = 0; + while (*spec) { + char* colon; + + items[last].incrementer = 1; + items[last].start = *spec++; + items[last].size = atoi(spec); + + total_size += port_data->header_size+items[last].size; + last++; + if ((colon = strchr(spec, ':')) == NULL) { + spec += strlen(spec); + } else { + *colon = '\0'; + spec = colon+1; + } + } + + buf = (char *) malloc(total_size); + if (buf == NULL) { + fprintf(stderr, "%s: insufficent memory for reply buffer of size %d\n", + port_data->progname, total_size); + exit(1); + } + + s = buf; + for (cur = 0; cur < last; cur++) { + int i; + size_t n; + + n = items[cur].size; + s += port_data->header_size; + for (i = 0; i < port_data->header_size; i++) { + *--s = (char) n; /* Store least significant byte. */ + n = n >> 8; + } + s += port_data->header_size; + + c = items[cur].start; + for (i = 0; i < items[cur].size; i++) { + *s++ = c; + c++; + if (c > 126) { + c = 33; + } + } + } + write_reply(buf, s-buf); +} + diff --git a/erts/emulator/test/port_SUITE_data/port_test.erl b/erts/emulator/test/port_SUITE_data/port_test.erl new file mode 100644 index 0000000000..56abfd5ded --- /dev/null +++ b/erts/emulator/test/port_SUITE_data/port_test.erl @@ -0,0 +1,36 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(port_test). + +-export([env/1, pwd/0]). + +env([A]) -> + Var = atom_to_list(A), + Val = os:getenv(Var), + case Val of + false -> + io:format("0~n"); + _ -> + io:format("1~s~n", [Val]) + end. + +pwd() -> + {ok, Pwd} = file:get_cwd(), + io:format("~s~n", [Pwd]). diff --git a/erts/emulator/test/port_SUITE_data/reclaim.h b/erts/emulator/test/port_SUITE_data/reclaim.h new file mode 100644 index 0000000000..1d57dc5b8a --- /dev/null +++ b/erts/emulator/test/port_SUITE_data/reclaim.h @@ -0,0 +1,60 @@ +#ifndef __RECLAIM_H__ +#define __RECLAIM_H__ + + +/* The Erlang release for VxWorks includes a simple mechanism for + "resource reclamation" at task exit - it allows replacement of the + functions that open/close "files" and malloc/free memory with versions + that keep track, to be able to "reclaim" file descriptors and memory + when a task exits (regardless of *how* it exits). + + The interface to this mechanism is made available via this file, + with the following caveats: + + - The interface may change (or perhaps even be removed, though that + isn't likely until VxWorks itself provides similar functionality) + in future releases - i.e. you must always use the version of this + file that comes with the Erlang release you are using. + + - Disaster is guaranteed if you use the mechanism incorrectly (see + below for the correct way), e.g. allocate memory with the "tracking" + version of malloc() and free it with the "standard" version of free(). + + - The mechanism (of course) incurs some performance penalty - thus + for a simple program you may be better off with careful programming, + making sure that you do whatever close()/free()/etc calls that are + appropriate at all exit points (though if you need to guard against + taskDelete() etc, things get messy...). + + To use the mechanism, simply program your application normally, i.e. + use open()/close()/malloc()/free() etc as usual, but #include this + file before any usage of the relevant functions. NOTE: To avoid the + "disaster" mentioned above, you *must* #include it in *all* (or none) + of the files that manipulate a particular file descriptor, allocated + memory area, etc. Finally, note that you can obviously not load your + application before the Erlang system when using this interface. +*/ + +/* Sorry, no ANSI prototypes yet... */ +extern int save_open(),save_creat(),save_socket(),save_accept(),save_close(); +#define open save_open +#define creat save_creat +#define socket save_socket +#define accept save_accept +#define close save_close +extern FILE *save_fopen(), *save_fdopen(), *save_freopen(); +extern int save_fclose(); +#define fopen save_fopen +#define fdopen save_fdopen +#define freopen save_freopen +#define fclose save_fclose +/* XXX Should do opendir/closedir too... */ +extern char *save_malloc(), *save_calloc(), *save_realloc(); +extern void save_free(), save_cfree(); +#define malloc save_malloc +#define calloc save_calloc +#define realloc save_realloc +#define free save_free +#define cfree save_cfree + +#endif diff --git a/erts/emulator/test/port_bif_SUITE.erl b/erts/emulator/test/port_bif_SUITE.erl new file mode 100644 index 0000000000..f4e0bb9fa8 --- /dev/null +++ b/erts/emulator/test/port_bif_SUITE.erl @@ -0,0 +1,446 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(port_bif_SUITE). + + +-export([all/1, command/1, command_e/1, + command_e_1/1, command_e_2/1, command_e_3/1, command_e_4/1, + port_info/1, port_info1/1, port_info2/1, + connect/1, control/1, echo_to_busy/1]). + +-export([do_command_e_1/1, do_command_e_2/1, do_command_e_4/1]). + +-export([init_per_testcase/2, fin_per_testcase/2]). + +-include("test_server.hrl"). + +all(suite) -> + [command, port_info, connect, control, echo_to_busy]. + + +init_per_testcase(_Func, Config) when is_list(Config) -> + Dog=test_server:timetrap(test_server:minutes(10)), + [{watchdog, Dog}|Config]. +fin_per_testcase(_Func, Config) when is_list(Config) -> + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog). + +command(Config) when is_list(Config) -> + ?line load_control_drv(Config), + + ?line P = open_port({spawn, control_drv}, []), + ?line do_command(P, "hello"), + ?line do_command(P, <<"hello">>), + ?line do_command(P, sub_bin(<<"1234kalle">>)), + ?line do_command(P, unaligned_sub_bin(<<"blurf">>)), + ?line do_command(P, ["bl"|unaligned_sub_bin(<<"urf">>)]), + ?line true = erlang:port_close(P), + ok. + +do_command(P, Data) -> + true = erlang:port_command(P, Data), + receive + {P,{data,Data}} -> + ok; + {P,{data,Data0}} -> + case {list_to_binary(Data0),list_to_binary([Data])} of + {B,B} -> ok; + _ -> test_server:fail({unexpected_data,Data0}) + end; + Other -> + test_server:fail({unexpected_message,Other}) + end. + + +command_e(suite) -> [command_e_1, + command_e_2, + command_e_3, + command_e_4]; +command_e(doc) -> "Tests port_command/2 with errors". + +%% port_command/2: badarg 1st arg +command_e_1(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line Program = filename:join(DataDir, "port_test"), + + process_flag(trap_exit, true), + ?line _ = spawn_link(?MODULE, do_command_e_1, [Program]), + ?line receive + {'EXIT', Pid, {badarg, _}} when is_pid(Pid) -> + ok; + Other -> + ?line test_server:fail(Other) + after 10000 -> + ?line test_server:fail(timeout) + end, + ok. + +do_command_e_1(Program) -> + ?line _ = open_port({spawn, Program}, []), + ?line erlang:port_command(apple, "plock"), + exit(survived). + +%% port_command/2: badarg 2nd arg +command_e_2(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line Program = filename:join(DataDir, "port_test"), + + process_flag(trap_exit, true), + ?line _ = spawn_link(?MODULE, do_command_e_2, [Program]), + ?line receive + {'EXIT', Pid, {badarg, _}} when is_pid(Pid) -> + ok; + Other -> + ?line test_server:fail(Other) + after 10000 -> + ?line test_server:fail(timeout) + end, + ok. + +do_command_e_2(Program) -> + ?line P = open_port({spawn, Program}, []), + ?line erlang:port_command(P, 1), + exit(survived). + +%% port_command/2: Posix signals trapped +command_e_3(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line Program = filename:join(DataDir, "port_test"), + + process_flag(trap_exit, true), + ?line P = open_port({spawn, Program}, [{packet, 1}]), + ?line Data = lists:duplicate(257, $a), + ?line erlang:port_command(P, Data), + ?line receive + {'EXIT', Port, einval} when is_port(Port) -> + ok; + Other -> + test_server:fail(Other) + after 10000 -> + test_server:fail(timeout) + end, + ok. + +%% port_command/2: Posix exit signals not trapped +command_e_4(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line Program = filename:join(DataDir, "port_test"), + + process_flag(trap_exit, true), + ?line _ = spawn_link(?MODULE, do_command_e_4, [Program]), + ?line receive + {'EXIT', Pid, {einval, _}} when is_pid(Pid) -> + ok; + Other -> + ?line test_server:fail(Other) + after 10000 -> + ?line test_server:fail(timeout) + end, + ok. + +do_command_e_4(Program) -> + ?line P = open_port({spawn, Program}, [{packet, 1}]), + ?line Data = lists:duplicate(257, $a), + ?line erlang:port_command(P, Data), + exit(survived). + +port_info(suite) -> [port_info1, port_info2]. + +%% Tests the port_info/1 BIF +port_info1(Config) when is_list(Config) -> + ?line load_control_drv(Config), + Me=self(), + ?line P = open_port({spawn, control_drv}, []), + ?line A1 = erlang:port_info(P), + ?line false = lists:keysearch(registered_name, 1, A1), + ?line register(myport, P), + ?line A = erlang:port_info(P), + ?line {value,{registered_name,myport}}= + lists:keysearch(registered_name, 1, A), + ?line {value,{name,"control_drv"}}=lists:keysearch(name, 1, A), + ?line {value,{links,[Me]}}=lists:keysearch(links, 1, A), + ?line {value,{id,_IdNum}}=lists:keysearch(id, 1, A), + ?line {value,{connected,_}}=lists:keysearch(connected, 1, A), + ?line {value,{input,0}}=lists:keysearch(input, 1, A), + ?line {value,{output,0}}=lists:keysearch(output, 1, A), + ?line true=erlang:port_close(P), + ok. + +%% Tests erlang:port_info/2" +port_info2(Config) when is_list(Config) -> + ?line load_control_drv(Config), + + ?line P = open_port({spawn,control_drv}, [binary]), + ?line [] = erlang:port_info(P, registered_name), + ?line register(myport, P), + ?line {registered_name, myport} = erlang:port_info(P, registered_name), + + ?line {name, "control_drv"}=erlang:port_info(P, name), + ?line {id, _IdNum} = erlang:port_info(P, id), + Me=self(), + ?line {links, [Me]} = erlang:port_info(P, links), + ?line {connected, Me} = erlang:port_info(P, connected), + ?line {input, 0}=erlang:port_info(P, input), + ?line {output,0}=erlang:port_info(P, output), + + ?line erlang:port_control(P, $i, "abc"), + ?line receive + {P,{data,<<"abc">>}} -> ok + end, + ?line {input,3} = erlang:port_info(P, input), + ?line {output,0} = erlang:port_info(P, output), + + ?line Bin = list_to_binary(lists:duplicate(2047, 42)), + ?line output_test(P, Bin, 3, 0), + + ?line true = erlang:port_close(P), + ok. + +output_test(_, _, Input, Output) when Output > 16#1fffffff -> + io:format("~p bytes received\n", [Input]); +output_test(P, Bin, Input0, Output0) -> + erlang:port_command(P, Bin), + receive + {P,{data,Bin}} -> ok; + Other -> + io:format("~p", [Other]), + ?line ?t:fail() + end, + Input = Input0 + size(Bin), + Output = Output0 + size(Bin), + {input,Input} = erlang:port_info(P, input), + {output,Output} = erlang:port_info(P, output), + + %% We can't test much here, but hopefully a debug-built emulator will crasch + %% if there is something wrong with the heap allocation. + case erlang:statistics(io) of + {{input,In},{output,Out}} when is_integer(In), is_integer(Out) -> + ok + end, + output_test(P, Bin, Input, Output). + +%% Tests the port_connect/2 BIF. +connect(Config) when is_list(Config) -> + ?line load_control_drv(Config), + + ?line P = open_port({spawn, control_drv}, []), + register(myport, P), + + ?line true = erlang:port_connect(myport, self()), + + %% Connect the port to another process. + + Data = "hello, world", + Parent = self(), + ?line Rec = + fun(Me) -> receive + {P,{data,Data}} -> + Parent ! connect_ok, + Me(Me) + end + end, + ?line RecPid = spawn_link(fun() -> Rec(Rec) end), + ?line true = erlang:port_connect(P, RecPid), + ?line unlink(P), + + %% Send a command to the port and make sure that the + %% other process receives the echo. + + ?line erlang:port_command(P, Data), + ?line receive + connect_ok -> ok + end, + + %% Tests some errors. + + ?line {'EXIT',{badarg, _}}=(catch erlang:port_connect(self(), self())), + ?line {'EXIT',{badarg, _}}=(catch erlang:port_connect(self(), P)), + ?line {'EXIT',{badarg, _}}=(catch erlang:port_connect(P, P)), + ?line {'EXIT',{badarg, _}}=(catch erlang:port_connect(P, xxxx)), + ?line {'EXIT',{badarg, _}}=(catch erlang:port_connect(P, [])), + + ?line process_flag(trap_exit, true), + ?line exit(P, you_should_die), + ?line receive + {'EXIT',RecPid,you_should_die} -> ok; + Other -> ?line ?t:fail({bad_message,Other}) + end, + + %% Done. + ok. + +%% Tests port_control/3 +control(Config) when is_list(Config) -> + ?line load_control_drv(Config), + ?line P = open_port({spawn, control_drv}, []), + + %% Test invalid (out-of-range) arguments. + + ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(self(), 1, [])), + + ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, -1, [])), + ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, -34887348739733833, [])), + ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, 16#100000000, [])), + ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, a, [])), + ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, 'e', dum)), + ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, $e, dum)), + ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, $e, fun(X) -> X end)), + ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, $e, + [fun(X) -> X end])), + ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, $e, + [1|fun(X) -> X end])), + + %% Test errors detected by the driver. + + ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, 177, [])), + ?line {'EXIT', {badarg, _}} = (catch erlang:port_control(P, 155, + random_packet(1024))), + + %% Test big op codes. + + register(myport, P), + ?line test_op(myport, 256), + ?line test_op(P, 256), + ?line test_op(P, 16#0033A837), + ?line test_op(P, 16#0ab37938), + ?line test_op(P, 16#eab37938), + ?line test_op(P, 16#ffffFFFF), + + %% Test the echo function of the driver. + + ?line echo(P, 0), + ?line echo(P, 1), + ?line echo(P, 10), + ?line echo(P, 13), + ?line echo(P, 63), + ?line echo(P, 64), + ?line echo(P, 65), + ?line echo(P, 127), + ?line echo(P, 1023), + ?line echo(P, 1024), + ?line echo(P, 11243), + ?line echo(P, 70000), + + %% Done. + + ?line true=erlang:port_close(myport), + ok. + +test_op(P, Op) -> + R = port_control(P, Op, []), + <<Op:32>> = list_to_binary(R). + +echo_to_busy(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line load_control_drv(Config), + ?line P = open_port({spawn, control_drv}, []), + ?line erlang:port_control(P, $b, [1]), % Set to busy. + Self = self(), + ?line Echoer = spawn(fun() -> echoer(P, Self) end), + ?line receive after 500 -> ok end, + ?line erlang:port_control(P, $b, [0]), % Set to not busy. + ?line receive + {Echoer, done} -> + ok; + {Echoer, Other} -> + test_server:fail(Other); + Other -> + test_server:fail({unexpected_message, Other}) + end, + ?line test_server:timetrap_cancel(Dog), + ok. + +echoer(P, ReplyTo) -> + Msg = random_packet(73), + true = erlang:port_connect(P, self()), + erlang:port_command(P, Msg), + receive + {P, {data, Msg}} -> + ReplyTo ! {self(), done}; + Other -> + ReplyTo ! {self(), {bad_message, Other}} + end. + +echo(P, Size) -> + io:format("Echo test, size ~w", [Size]), + Packet = random_packet(Size), + Packet = erlang:port_control(P, $e, Packet), + Bin = list_to_binary(Packet), + Packet = erlang:port_control(P, $e, Bin), + Packet = erlang:port_control(P, $e, sub_bin(Bin)), + Packet = erlang:port_control(P, $e, unaligned_sub_bin(Bin)), + Packet = erlang:port_control(P, $e, [unaligned_sub_bin(Bin)]). + +load_control_drv(Config) when is_list(Config) -> + ?line DataDir = ?config(data_dir, Config), + ?line erl_ddll:start(), + ?line ok = load_driver(DataDir, "control_drv"). + +load_driver(Dir, Driver) -> + case erl_ddll:load_driver(Dir, Driver) of + ok -> ok; + {error, Error} = Res -> + io:format("~s\n", [erl_ddll:format_error(Error)]), + Res + end. + +random_packet(Size) -> + random_packet(Size, "", random_char()). + +random_packet(0, Result, _NextChar) -> + Result; +random_packet(Left, Result, NextChar0) -> + NextChar = + if + NextChar0 >= 126 -> + 33; + true -> + NextChar0+1 + end, + random_packet(Left-1, [NextChar0|Result], NextChar). + +random_char() -> + random_char("abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ0123456789"). + +random_char(Chars) -> + lists:nth(uniform(length(Chars)), Chars). + +uniform(N) -> + case get(random_seed) of + undefined -> + {X, Y, Z} = time(), + random:seed(X, Y, Z); + _ -> + ok + end, + random:uniform(N). + +unaligned_sub_bin(Bin0) -> + Bin1 = <<0:3,Bin0/binary,31:5>>, + Sz = size(Bin0), + <<0:3,Bin:Sz/binary,31:5>> = id(Bin1), + Bin. + +sub_bin(Bin) when is_binary(Bin) -> + {_,B} = split_binary(list_to_binary([0,1,3,Bin]), 3), + B. + +id(I) -> I. + diff --git a/erts/emulator/test/port_bif_SUITE_data/Makefile.src b/erts/emulator/test/port_bif_SUITE_data/Makefile.src new file mode 100644 index 0000000000..1a2d348ecb --- /dev/null +++ b/erts/emulator/test/port_bif_SUITE_data/Makefile.src @@ -0,0 +1,14 @@ +CC = @CC@ +LD = @LD@ +CFLAGS = @CFLAGS@ -I@erl_include@ @DEFS@ +CROSSLDFLAGS = @CROSSLDFLAGS@ + +all: control_drv@dll@ port_test@exe@ + +port_test@exe@: port_test@obj@ + $(LD) $(CROSSLDFLAGS) -o port_test port_test@obj@ @LIBS@ + +port_test@obj@: port_test.c + $(CC) -c -o port_test@obj@ $(CFLAGS) port_test.c + +@SHLIB_RULES@ diff --git a/erts/emulator/test/port_bif_SUITE_data/control_drv.c b/erts/emulator/test/port_bif_SUITE_data/control_drv.c new file mode 100644 index 0000000000..e9f57a887a --- /dev/null +++ b/erts/emulator/test/port_bif_SUITE_data/control_drv.c @@ -0,0 +1,84 @@ +#include <stdio.h> +#include <stdlib.h> +#include "erl_driver.h" + + +static ErlDrvPort erlang_port; +static ErlDrvData control_start(ErlDrvPort, char*); +static void control_stop(ErlDrvData); +static void control_read(ErlDrvData, char*, int); +static int control_control(ErlDrvData, unsigned int, char*, int, char**, int); + +static ErlDrvEntry control_driver_entry = +{ + NULL, + control_start, + control_stop, + control_read, + NULL, + NULL, + "control_drv", + NULL, + NULL, + control_control, + NULL, + NULL, + NULL +}; + +DRIVER_INIT(control_drv) +{ + erlang_port = (ErlDrvPort)-1; + return &control_driver_entry; +} + +static ErlDrvData control_start(ErlDrvPort port,char *buf) +{ + if (erlang_port != (ErlDrvPort)-1) + return ERL_DRV_ERROR_GENERAL; + + erlang_port = port; + return (ErlDrvData)port; +} + +static void control_read(ErlDrvData port, char *buf, int count) +{ + driver_output(erlang_port, buf, count); +} + +static void control_stop(ErlDrvData port) +{ + erlang_port = (ErlDrvPort)-1; +} + +static int control_control(ErlDrvData port, unsigned command, char* buf, int count, + char** res, int res_size) +{ + switch (command) { + case 'e': + if (count > res_size) { + *res = (char *) driver_alloc(count); + } + memcpy(*res, buf, count); + return count; + case 'b': + set_busy_port(erlang_port, buf[0]); + return 0; + case 'i': + driver_output(erlang_port, buf, count); + return 0; + default: + if (command < 256) { + return -1; + } else { + char* p = *res; + int i; + + for (i = 3; i >= 0; i--) { + p[i] = command; + command >>= 8; + } + return 4; + } + } +} diff --git a/erts/emulator/test/port_bif_SUITE_data/port_test.c b/erts/emulator/test/port_bif_SUITE_data/port_test.c new file mode 100644 index 0000000000..c6b128df66 --- /dev/null +++ b/erts/emulator/test/port_bif_SUITE_data/port_test.c @@ -0,0 +1,602 @@ +/* + * Author: Bjorn Gustavsson + * Purpose: A port program to be used for testing the open_port bif. + */ + +#ifdef VXWORKS +#include <vxWorks.h> +#include <taskVarLib.h> +#include <taskLib.h> +#include <sysLib.h> +#include <string.h> +#include <ioLib.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#ifndef __WIN32__ +#include <unistd.h> + +#ifdef VXWORKS +#include "reclaim.h" +#include <sys/times.h> +#else +#include <sys/time.h> +#endif + +#define O_BINARY 0 +#define _setmode(fd, mode) +#endif + +#ifdef __WIN32__ +#include "windows.h" +#include "winbase.h" +#endif + + +#ifdef VXWORKS +#define REDIR_STDOUT(fd) ioTaskStdSet(0, 1, fd); +#else +#define REDIR_STDOUT(fd) if (dup2(fd, 1) == -1) { \ + fprintf(stderr, "%s: failed to duplicate handle %d to 1: %d\n", \ + port_data->progname, fd, errno); \ + exit(1); \ +} +#endif + +#ifdef VXWORKS +#define MAIN(argc, argv) port_test(argc, argv) +#else +#define MAIN(argc, argv) main(argc, argv) +#endif + + +extern int errno; + +typedef struct { + char* progname; /* Name of this program (from argv[0]). */ + int header_size; /* Number of bytes in each packet header: + * 1, 2, or 4, or 0 for a continous byte stream. */ + int fd_from_erl; /* File descriptor from Erlang. */ + int fd_to_erl; /* File descriptor to Erlang. */ + unsigned char* io_buf; /* Buffer for file i/o. */ + int io_buf_size; /* Current size of i/o buffer. */ + int delay_mode; /* If set, this program will wait 5 seconds + * after reading the header for a packet + * before reading the rest. + */ + int break_mode; /* If set, this program will close standard + * input, which should case broken pipe + * error in the writer. + */ + int quit_mode; /* If set, this program will exit + * just after reading the packet header. + */ + int slow_writes; /* Writes back the reply in chunks with + * sleeps in between. The value is the + * chunk size. If 0, normal writes are done. + */ + char* output_file; /* File into which the result will be written. */ + int no_packet_loop; /* No packet loop. */ + + int limited_bytecount; /* Only answer a limited number of bytes, then exit (stream mode) */ + +} PORT_TEST_DATA; + +PORT_TEST_DATA* port_data; + +static int packet_loop(); +static void reply(); +static void write_reply(); +static void ensure_buf_big_enough(); +static int readn(); +static void delay(unsigned ms); +static void dump(unsigned char* buf, int sz, int max); +static void replace_stdout(char* filename); +static void generate_reply(char* spec); + +#ifndef VXWORKS +#ifndef HAVE_STRERROR +extern int sys_nerr; +#ifndef sys_errlist /* sys_errlist is sometimes defined to + call a function on win32 */ +extern char *sys_errlist[]; +#endif + +char* +strerror(err) +int err; +{ + static char msgstr[1024]; + + if (err == 0) { + msgstr[0] = '\0'; + } else if (0 < err && err < sys_nerr) { + strcpy(msgstr, sys_errlist[err]); + } else { + sprintf(msgstr, "Unknown error %d", err); + } + return msgstr; +} +#endif +#endif + + +MAIN(argc, argv) +int argc; +char *argv[]; +{ + int ret; +#ifdef VXWORKS + if(taskVarAdd(0, (int *)&port_data) != OK) { + fprintf(stderr, "Can't do taskVarAdd in port_test\n"); + exit(1); + } +#endif + if((port_data = (PORT_TEST_DATA *) malloc(sizeof(PORT_TEST_DATA))) == NULL) { + fprintf(stderr, "Couldn't malloc for port_data"); + exit(1); + } + port_data->header_size = 0; + port_data->io_buf_size = 0; + port_data->delay_mode = 0; + port_data->break_mode = 0; + port_data->quit_mode = 0; + port_data->slow_writes = 0; + port_data->output_file = NULL; + port_data->no_packet_loop = 0; + + port_data->progname = argv[0]; + port_data->fd_from_erl = 0; + port_data->fd_to_erl = 1; + + port_data->limited_bytecount = 0; + + _setmode(0, _O_BINARY); + _setmode(1, _O_BINARY); + + while (argc > 1 && argv[1][0] == '-') { + switch (argv[1][1]) { + case 'b': /* Break mode. */ + port_data->break_mode = 1; + break; + case 'c': /* Close standard output. */ + close(port_data->fd_to_erl); + break; + case 'd': /* Delay mode. */ + port_data->delay_mode = 1; + break; + case 'n': /* No packet loop. */ + port_data->no_packet_loop = 1; + break; + case 'o': /* Output to file. */ + port_data->output_file = argv[1]+2; + break; + case 'q': /* Quit mode. */ + port_data->quit_mode = 1; + break; + case 'r': /* Generate reply. */ + generate_reply(argv[1]+2); + break; + case 's': /* Slow writes. */ + port_data->slow_writes = atoi(argv[1]+2); + break; + case 'h': /* Header size for packets. */ + switch (argv[1][2]) { + case '0': port_data->header_size = 0; break; + case '1': port_data->header_size = 1; break; + case '2': port_data->header_size = 2; break; + case '4': port_data->header_size = 4; break; + case '\0': + fprintf(stderr, "%s: missing header size for -h\n", port_data->progname); + return 1; + default: + fprintf(stderr, "%s: illegal packet header size: %c\n", + port_data->progname, argv[1][2]); + return 1; + } + break; + case 'e': + port_data->fd_to_erl = 2; + break; + case 'l': + port_data->limited_bytecount = atoi(argv[1]+2); + break; + default: + fprintf(stderr, "Unrecognized switch: %s\n", argv[1]); + free(port_data); + exit(1); + } + argc--, argv++; + } + + if (argc > 1) { + /* XXX Add error printout here */ + } + + if (port_data->no_packet_loop){ + free(port_data); + exit(0); + } + + /* + * If an output file was given, let it replace standard output. + */ + + if (port_data->output_file) + replace_stdout(port_data->output_file); + + ret = packet_loop(); + if(port_data->io_buf_size > 0) + free(port_data->io_buf); + free(port_data); + return ret; +} + +static int +packet_loop(void) +{ + int total_read = 0; + port_data->io_buf = (unsigned char*) malloc(1); /* Allocate once, so realloc works (SunOS) */ + + + for (;;) { + int packet_length; /* Length of current packet. */ + int i; + int bytes_read; /* Number of bytes read. */ + + /* + * Read the packet header, if any. + */ + + if (port_data->header_size == 0) { + if(port_data->limited_bytecount && + port_data->limited_bytecount - total_read < 4096) + packet_length = port_data->limited_bytecount - total_read; + else + packet_length = 4096; + } else { + ensure_buf_big_enough(port_data->header_size); + if (readn(port_data->fd_from_erl, port_data->io_buf, port_data->header_size) != port_data->header_size) { + return(1); + } + + /* + * Get the length of this packet. + */ + + packet_length = 0; + for (i = 0; i < port_data->header_size; i++) + packet_length = (packet_length << 8) | port_data->io_buf[i]; + } + + + /* + * Delay if delay mode. + */ + + if (port_data->delay_mode) { + delay(5000L); + } + + if (port_data->quit_mode) { + return(1); + } else if (port_data->break_mode) { + close(0); + delay(32000L); + return(1); + } + + /* + * Read the packet itself. + */ + + ensure_buf_big_enough(packet_length+4+1); /* At least five bytes. */ + port_data->io_buf[4] = '\0'; + if (port_data->header_size == 0) { + bytes_read = read(port_data->fd_from_erl, port_data->io_buf+4, packet_length); + if (bytes_read == 0) + return(1); + if (bytes_read < 0) { + fprintf(stderr, "Error reading %d bytes: %s\n", + packet_length, strerror(errno)); + return(1); + } + total_read += bytes_read; + } else { + bytes_read = readn(port_data->fd_from_erl, port_data->io_buf+4, packet_length); + if (bytes_read != packet_length) { + fprintf(stderr, "%s: couldn't read packet of length %d\r\n", + port_data->progname, packet_length); + return(1); + } + } + + /* + * Act on the command. + */ + if (port_data->header_size == 0) { + reply(port_data->io_buf+4, bytes_read); + if(port_data->limited_bytecount && + port_data->limited_bytecount <= total_read){ + delay(5000L); + return(0); + } + } else { + switch (port_data->io_buf[4]) { + case 'p': /* ping */ + port_data->io_buf[4] = 'P'; + reply(port_data->io_buf+4, bytes_read); + break; + case 'e': /* echo */ + reply(port_data->io_buf+4, bytes_read); + break; + default: + fprintf(stderr, "%s: bad packet of length %d received: ", + port_data->progname, bytes_read); + dump(port_data->io_buf+4, bytes_read, 10); + fprintf(stderr, "\r\n"); + return(1); + } + } + } +} + +/* + * Sends a packet back to Erlang. + */ + +static void +reply(buf, size) + char* buf; /* Buffer with reply. The four bytes before + * this pointer must be allocated so that + * this function can put the header there. + */ + int size; /* Size of buffer to send. */ +{ + int n; /* Temporary to hold size. */ + int i; /* Loop counter. */ + + /* + * Fill the header starting with the least significant byte + * (this will work even if there is no header). + */ + + n = size; + for (i = 0; i < port_data->header_size; i++) { + *--buf = (char) n; /* Store least significant byte. */ + n = n >> 8; + } + + size += port_data->header_size; + write_reply(buf, size); +} + + + +static void +write_reply(buf, size) + char* buf; /* Buffer with reply. Must contain header. */ + int size; /* Size of buffer to send. */ +{ + int n; /* Temporary to hold size. */ + + if (port_data->slow_writes <= 0) { /* Normal, "fast", write. */ + write(port_data->fd_to_erl, buf, size); + } else { + /* + * Write chunks with delays in between. + */ + + while (size > 0) { + n = size > port_data->slow_writes ? port_data->slow_writes : size; + write(port_data->fd_to_erl, buf, n); + size -= n; + buf += n; + if (size) + delay(500L); + } + } +} + + +/* + * Ensures that our I/O buffer is big enough for the packet to come. + */ + +static void +ensure_buf_big_enough(size) + int size; /* Needed size of buffer. */ +{ + if (port_data->io_buf_size >= size) + return; + + port_data->io_buf = (unsigned char*) realloc(port_data->io_buf, size); + if (port_data->io_buf == NULL) { + fprintf(stderr, "%s: insufficient memory for i/o buffer of size %d\n", + port_data->progname, size); + exit(1); + } + port_data->io_buf_size = size; +} + +/* + * Reads len number of bytes. + */ +static int +readn(fd, buf, len) + int fd; /* File descriptor to read from. */ + unsigned char *buf; /* Store in this buffer. */ + int len; /* Number of bytes to read. */ +{ + int n; /* Byte count in last read call. */ + int sofar; /* Bytes read so far. */ + + sofar = 0; + do { + if ((n = read(fd, buf+sofar, len-sofar)) <= 0) + /* error or EOF in read */ + return(n); + sofar += n; + } while (sofar < len); + return sofar; +} + +static void +replace_stdout(filename) +char* filename; /* Name of file to replace standard output. */ +{ + int fd; + + fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0666); + if (fd == -1) { + fprintf(stderr, "%s: failed to open %s for writing: %d\n", + port_data->progname, filename, errno); + exit(1); + } + REDIR_STDOUT(fd); +} + +static void +dump(buf, sz, max) + unsigned char* buf; + int sz; + int max; +{ + int i, imax; + char comma[5]; + + comma[0] = ','; + comma[1] = '\0'; + if (!sz) + return; + if (sz > max) + imax = max; + else + imax = sz; + + for (i=0; i<imax; i++) { + if (i == imax-1) { + if (sz > max) + strcpy(comma, ",..."); + else + comma[0] = 0; + } + if (isdigit(buf[i])) { + fprintf(stderr, "%u%s", (int)(buf[i]), comma); + } else { + if (isalpha(buf[i])) { + fprintf(stderr, "%c%s", buf[i], comma); + } + else { + fprintf(stderr, "%u%s", (int)(buf[i]), comma); + } + } + } +} + +/* + * Delays (sleeps) the given number of milli-seconds. + */ + +static void +delay(unsigned ms) +{ +#ifdef VXWORKS + taskDelay((sysClkRateGet() * ms) / 1000); +#else +#ifdef __WIN32__ + Sleep(ms); +#else + struct timeval t; + t.tv_sec = ms/1000; + t.tv_usec = (ms % 1000) * 1000; + + select(0, NULL, NULL, NULL, &t); +#endif +#endif +} + +/* + * Generates a reply buffer given the specification. + * + * <packet-bytes>,<start-character>,<increment>,<size> + * + * Where: + * <packet-bytes> is + */ +static void +generate_reply(spec) +char* spec; /* Specification for reply. */ +{ + typedef struct item { + int start; /* Start character. */ + int incrementer; /* How much to increment. */ + size_t size; /* Size of reply buffer. */ + } Item; + + Item items[256]; + int last; + int cur; + size_t total_size; + char* buf; /* Reply buffer. */ + char* s; /* Current pointer into buffer. */ + int c; + + total_size = 0; + last = 0; + while (*spec) { + char* colon; + + items[last].incrementer = 1; + items[last].start = *spec++; + items[last].size = atoi(spec); + + total_size += port_data->header_size+items[last].size; + last++; + if ((colon = strchr(spec, ':')) == NULL) { + spec += strlen(spec); + } else { + *colon = '\0'; + spec = colon+1; + } + } + + buf = (char *) malloc(total_size); + if (buf == NULL) { + fprintf(stderr, "%s: insufficent memory for reply buffer of size %d\n", + port_data->progname, total_size); + exit(1); + } + + s = buf; + for (cur = 0; cur < last; cur++) { + int i; + size_t n; + + n = items[cur].size; + s += port_data->header_size; + for (i = 0; i < port_data->header_size; i++) { + *--s = (char) n; /* Store least significant byte. */ + n = n >> 8; + } + s += port_data->header_size; + + c = items[cur].start; + for (i = 0; i < items[cur].size; i++) { + *s++ = c; + c++; + if (c > 126) { + c = 33; + } + } + } + write_reply(buf, s-buf); +} + diff --git a/erts/emulator/test/port_bif_SUITE_data/reclaim.h b/erts/emulator/test/port_bif_SUITE_data/reclaim.h new file mode 100644 index 0000000000..1d57dc5b8a --- /dev/null +++ b/erts/emulator/test/port_bif_SUITE_data/reclaim.h @@ -0,0 +1,60 @@ +#ifndef __RECLAIM_H__ +#define __RECLAIM_H__ + + +/* The Erlang release for VxWorks includes a simple mechanism for + "resource reclamation" at task exit - it allows replacement of the + functions that open/close "files" and malloc/free memory with versions + that keep track, to be able to "reclaim" file descriptors and memory + when a task exits (regardless of *how* it exits). + + The interface to this mechanism is made available via this file, + with the following caveats: + + - The interface may change (or perhaps even be removed, though that + isn't likely until VxWorks itself provides similar functionality) + in future releases - i.e. you must always use the version of this + file that comes with the Erlang release you are using. + + - Disaster is guaranteed if you use the mechanism incorrectly (see + below for the correct way), e.g. allocate memory with the "tracking" + version of malloc() and free it with the "standard" version of free(). + + - The mechanism (of course) incurs some performance penalty - thus + for a simple program you may be better off with careful programming, + making sure that you do whatever close()/free()/etc calls that are + appropriate at all exit points (though if you need to guard against + taskDelete() etc, things get messy...). + + To use the mechanism, simply program your application normally, i.e. + use open()/close()/malloc()/free() etc as usual, but #include this + file before any usage of the relevant functions. NOTE: To avoid the + "disaster" mentioned above, you *must* #include it in *all* (or none) + of the files that manipulate a particular file descriptor, allocated + memory area, etc. Finally, note that you can obviously not load your + application before the Erlang system when using this interface. +*/ + +/* Sorry, no ANSI prototypes yet... */ +extern int save_open(),save_creat(),save_socket(),save_accept(),save_close(); +#define open save_open +#define creat save_creat +#define socket save_socket +#define accept save_accept +#define close save_close +extern FILE *save_fopen(), *save_fdopen(), *save_freopen(); +extern int save_fclose(); +#define fopen save_fopen +#define fdopen save_fdopen +#define freopen save_freopen +#define fclose save_fclose +/* XXX Should do opendir/closedir too... */ +extern char *save_malloc(), *save_calloc(), *save_realloc(); +extern void save_free(), save_cfree(); +#define malloc save_malloc +#define calloc save_calloc +#define realloc save_realloc +#define free save_free +#define cfree save_cfree + +#endif diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl new file mode 100644 index 0000000000..fdedf30e78 --- /dev/null +++ b/erts/emulator/test/process_SUITE.erl @@ -0,0 +1,2067 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(process_SUITE). + +%% Tests processes, trapping exit messages and the BIFs: +%% exit/1 +%% exit/2 +%% process_info/1,2 +%% register/2 (partially) + +-include("test_server.hrl"). + +-define(heap_binary_size, 64). + +-export([all/1, spawn_with_binaries/1, + t_exit_1/1, t_exit_2/1, t_exit_2_other/1, t_exit_2_other_normal/1, + self_exit/1, normal_suicide_exit/1, abnormal_suicide_exit/1, + t_exit_2_catch/1, trap_exit_badarg/1, trap_exit_badarg_in_bif/1, + exit_and_timeout/1, exit_twice/1, + t_process_info/1, process_info_other_msg/1, + process_info_other_dist_msg/1, + process_info_2_list/1, process_info_lock_reschedule/1, + process_info_lock_reschedule2/1, + bump_reductions/1, low_prio/1, binary_owner/1, yield/1, yield2/1, + process_status_exiting/1, + otp_4725/1, bad_register/1, garbage_collect/1, otp_6237/1, + process_info_messages/1, process_flag_badarg/1, + processes_large_tab/1, processes_default_tab/1, processes_small_tab/1, + processes_this_tab/1, processes_apply_trap/1, + processes_last_call_trap/1, processes_gc_trap/1, + processes_term_proc_list/1, processes_bif/1, + otp_7738/1, otp_7738_waiting/1, otp_7738_suspended/1, + otp_7738_resume/1]). +-export([prio_server/2, prio_client/2]). + +-export([init_per_testcase/2, fin_per_testcase/2, end_per_suite/1]). + +-export([hangaround/2, processes_bif_test/0, do_processes/1, + processes_term_proc_list_test/1]). + +all(suite) -> + [spawn_with_binaries, t_exit_1, t_exit_2, + trap_exit_badarg, trap_exit_badarg_in_bif, + t_process_info, process_info_other_msg, process_info_other_dist_msg, + process_info_2_list, + process_info_lock_reschedule, process_info_lock_reschedule2, + process_status_exiting, + bump_reductions, low_prio, yield, yield2, otp_4725, bad_register, + garbage_collect, process_info_messages, process_flag_badarg, otp_6237, + processes_bif, + otp_7738]. + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog=?t:timetrap(?t:minutes(10)), + [{watchdog, Dog},{testcase, Func}|Config]. + +fin_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +end_per_suite(Config) -> + catch erts_debug:set_internal_state(available_internal_state, false), + Config. + +fun_spawn(Fun) -> + spawn_link(erlang, apply, [Fun, []]). + +%% Tests that binaries as arguments to spawn/3 doesn't leak +%% (unclear if this test case will actually prove anything on +%% a modern computer with lots of memory). +spawn_with_binaries(Config) when is_list(Config) -> + ?line L = lists:duplicate(2048, 42), + ?line TwoMeg = lists:duplicate(1024, L), + ?line Fun = fun() -> spawn(?MODULE, binary_owner, [list_to_binary(TwoMeg)]), + receive after 1 -> ok end end, + ?line Iter = case test_server:purify_is_running() of + true -> 10; + false -> 150 + end, + ?line test_server:do_times(Iter, Fun), + ok. + +binary_owner(Bin) when is_binary(Bin) -> + ok. + +%% Tests exit/1 with a big message. +t_exit_1(Config) when is_list(Config) -> + ?line start_spawner(), + ?line Dog = test_server:timetrap(test_server:seconds(20)), + ?line process_flag(trap_exit, true), + ?line test_server:do_times(10, fun t_exit_1/0), + ?line test_server:timetrap_cancel(Dog), + ?line stop_spawner(), + ok. + +t_exit_1() -> + ?line Pid = fun_spawn(fun() -> exit(kb_128()) end), + ?line Garbage = kb_128(), + ?line receive + {'EXIT', Pid, Garbage} -> ok + end. + +t_exit_2(suite) -> [t_exit_2_other, t_exit_2_other_normal, + self_exit, normal_suicide_exit, + abnormal_suicide_exit, t_exit_2_catch, + exit_and_timeout, exit_twice]. + +%% Tests exit/2 with a lot of data in the exit message. +t_exit_2_other(Config) when is_list(Config) -> + ?line start_spawner(), + ?line Dog = test_server:timetrap(test_server:seconds(20)), + ?line process_flag(trap_exit, true), + ?line test_server:do_times(10, fun t_exit_2_other/0), + ?line test_server:timetrap_cancel(Dog), + ?line stop_spawner(), + ok. + +t_exit_2_other() -> + ?line Pid = fun_spawn(fun() -> receive x -> ok end end), + ?line Garbage = kb_128(), + ?line exit(Pid, Garbage), + ?line receive + {'EXIT', Pid, Garbage} -> ok + end. + +%% Tests that exit(Pid, normal) does not kill another process.; +t_exit_2_other_normal(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(20)), + ?line process_flag(trap_exit, true), + ?line Pid = fun_spawn(fun() -> receive x -> ok end end), + ?line exit(Pid, normal), + ?line receive + {'EXIT', Pid, Reason} -> + ?line test_server:fail({process_died, Reason}) + after 1000 -> + ok + end, + ?line case process_info(Pid) of + undefined -> + test_server:fail(process_died_on_normal); + List when is_list(List) -> + ok + end, + exit(Pid, kill), + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Tests that we can trap an exit message sent with exit/2 from +%% the same process. +self_exit(Config) when is_list(Config) -> + ?line start_spawner(), + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line process_flag(trap_exit, true), + ?line test_server:do_times(200, fun self_exit/0), + ?line test_server:timetrap_cancel(Dog), + ?line stop_spawner(), + ok. + +self_exit() -> + ?line Garbage = eight_kb(), + ?line P = self(), + ?line true = exit(P, Garbage), + ?line receive + {'EXIT', P, Garbage} -> ok + end. + +%% Tests exit(self(), normal) is equivalent to exit(normal) for a process +%% that doesn't trap exits. +normal_suicide_exit(Config) when is_list(Config) -> + ?line process_flag(trap_exit, true), + ?line Pid = fun_spawn(fun() -> exit(self(), normal) end), + ?line receive + {'EXIT', Pid, normal} -> ok; + Other -> test_server:fail({bad_message, Other}) + end. + +%% Tests exit(self(), Term) is equivalent to exit(Term) for a process +%% that doesn't trap exits."; +abnormal_suicide_exit(Config) when is_list(Config) -> + ?line Garbage = eight_kb(), + ?line process_flag(trap_exit, true), + ?line Pid = fun_spawn(fun() -> exit(self(), Garbage) end), + ?line receive + {'EXIT', Pid, Garbage} -> ok; + Other -> test_server:fail({bad_message, Other}) + end. + +%% Tests that exit(self(), die) cannot be catched. +t_exit_2_catch(Config) when is_list(Config) -> + ?line process_flag(trap_exit, true), + ?line Pid = fun_spawn(fun() -> catch exit(self(), die) end), + ?line receive + {'EXIT', Pid, normal} -> + test_server:fail(catch_worked); + {'EXIT', Pid, die} -> + ok; + Other -> + test_server:fail({bad_message, Other}) + end. + +%% Tests trapping of an 'EXIT' message generated by a bad argument to +%% the abs/1 bif. The 'EXIT' message will intentionally be very big. +trap_exit_badarg(Config) when is_list(Config) -> + ?line start_spawner(), + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line process_flag(trap_exit, true), + ?line test_server:do_times(10, fun trap_exit_badarg/0), + ?line test_server:timetrap_cancel(Dog), + ?line stop_spawner(), + ok. + +trap_exit_badarg() -> + ?line Pid = fun_spawn(fun() -> bad_guy(kb_128()) end), + ?line Garbage = kb_128(), + ?line receive + {'EXIT', Pid, {badarg,[{erlang,abs,[Garbage]},{?MODULE,bad_guy,1}|_]}} -> + ok; + Other -> + ?line ok = io:format("Bad EXIT message: ~P", [Other, 30]), + ?line test_server:fail(bad_exit_message) + end. + +bad_guy(Arg) -> + ?line abs(Arg). + + +kb_128() -> + Eight = eight_kb(), + {big_binary(), + Eight, Eight, Eight, Eight, Eight, Eight, Eight, Eight, + big_binary(), + Eight, Eight, Eight, Eight, Eight, Eight, Eight, Eight, + big_binary()}. + +eight_kb() -> + %%% This is really much more than eight kb, so vxworks platforms + %%% gets away with 1/8 of the other platforms (due to limited + %%% memory resources). + B64 = case os:type() of + vxworks -> + ?line lists:seq(1, 8); + _ -> + ?line lists:seq(1, 64) + end, + ?line B512 = {<<1>>,B64,<<2,3>>,B64,make_unaligned_sub_binary(<<4,5,6,7,8,9>>), + B64,make_sub_binary([1,2,3,4,5,6]), + B64,make_sub_binary(lists:seq(1, ?heap_binary_size+1)), + B64,B64,B64,B64,big_binary()}, + ?line lists:duplicate(8, {B512,B512}). + +big_binary() -> + big_binary(10, [42]). +big_binary(0, Acc) -> + list_to_binary(Acc); +big_binary(N, Acc) -> + big_binary(N-1, [Acc|Acc]). + +%% Test receiving an EXIT message when spawning a BIF with bad arguments. +trap_exit_badarg_in_bif(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line process_flag(trap_exit, true), + ?line test_server:do_times(10, fun trap_exit_badarg_bif/0), + ?line test_server:timetrap_cancel(Dog), + ok. + +trap_exit_badarg_bif() -> + ?line Pid = spawn_link(erlang, node, [1]), + ?line receive + {'EXIT', Pid, {badarg, _}} -> + ok; + Other -> + ?line test_server:fail({unexpected, Other}) + end. + +%% The following sequences of events have crasched Beam. +%% +%% 1) An exit is sent to a process which is currently not running. +%% The exit reason will (on purpose) overwrite the message queue +%% pointer. +%% 2) Before the process is scheduled in, it receives a timeout (from +%% a 'receive after'). +%% 3) The process will crash the next time it executes 'receive'. + +exit_and_timeout(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(20)), + + ?line process_flag(trap_exit, true), + ?line Parent = self(), + ?line Low = fun_spawn(fun() -> eat_low(Parent) end), + ?line High = fun_spawn(fun() -> eat_high(Low) end), + ?line eat_wait_for(Low, High), + + ?line test_server:timetrap_cancel(Dog), + ok. + + +eat_wait_for(Low, High) -> + ?line receive + {'EXIT', Low, {you, are, dead}} -> + ok; + {'EXIT', High, normal} -> + eat_wait_for(Low, High); + Other -> + test_server:fail({bad_message, Other}) + end. + +eat_low(_Parent) -> + receive + after 2500 -> + ok + end, + receive + Any -> + io:format("Received: ~p\n", [Any]) + after 1000 -> + ok + end. + +eat_high(Low) -> + process_flag(priority, high), + receive after 1000 -> ok end, + exit(Low, {you, are, dead}), + {_, Sec, _} = now(), + loop(Sec, Sec). + +%% Busy loop for 5 seconds. + +loop(OrigSec, CurrentSec) when CurrentSec < OrigSec+5 -> + {_, NewSec, _} = now(), + loop(OrigSec, NewSec); +loop(_, _) -> + ok. + + +%% Tries to send two different exit messages to a process. +%% (The second one should be ignored.) +exit_twice(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(20)), + + ?line process_flag(trap_exit, true), + ?line Low = fun_spawn(fun etwice_low/0), + ?line High = fun_spawn(fun() -> etwice_high(Low) end), + ?line etwice_wait_for(Low, High), + + ?line test_server:timetrap_cancel(Dog), + ok. + +etwice_wait_for(Low, High) -> + ?line receive + {'EXIT', Low, first} -> + ok; + {'EXIT', Low, Other} -> + test_server:fail({wrong_exit_reason, Other}); + {'EXIT', High, normal} -> + etwice_wait_for(Low, High); + Other -> + test_server:fail({bad_message, Other}) + end. + +etwice_low() -> + etwice_low(). + +etwice_high(Low) -> + process_flag(priority, high), + exit(Low, first), + exit(Low, second). + +%% Tests the process_info/1 BIF. +t_process_info(Config) when is_list(Config) -> + ?line [] = process_info(self(), registered_name), + ?line register(my_name, self()), + ?line {registered_name, my_name} = process_info(self(), registered_name), + ?line {status, running} = process_info(self(), status), + ?line {current_function, {?MODULE, t_process_info, 1}} = + process_info(self(), current_function), + ?line Gleader = group_leader(), + ?line {group_leader, Gleader} = process_info(self(), group_leader), + ?line {'EXIT',{badarg,_Info}} = (catch process_info('not_a_pid')), + ok. + +%% Tests the process_info/1 BIF on another process with messages. +process_info_other_msg(Config) when is_list(Config) -> + Self = self(), + ?line Pid = spawn_link(fun() -> other_process(Self) end), + receive + {go_ahead,Pid} -> ok + end, + + ?line Own = {my,own,message}, + + ?line {messages,[Own]} = process_info(Pid, messages), + + ?line Garbage = kb_128(), + ?line MsgA = {a,Garbage}, + ?line MsgB = {b,Garbage}, + ?line MsgC = {c,Garbage}, + ?line MsgD = {d,Garbage}, + ?line MsgE = {e,Garbage}, + + ?line Pid ! MsgA, + ?line {messages,[Own,MsgA]} = process_info(Pid, messages), + ?line Pid ! MsgB, + ?line {messages,[Own,MsgA,MsgB]} = process_info(Pid, messages), + ?line Pid ! MsgC, + ?line {messages,[Own,MsgA,MsgB,MsgC]} = process_info(Pid, messages), + ?line Pid ! MsgD, + ?line {messages,[Own,MsgA,MsgB,MsgC,MsgD]} = process_info(Pid, messages), + ?line Pid ! MsgE, + ?line {messages,[Own,MsgA,MsgB,MsgC,MsgD,MsgE]=All} = process_info(Pid, messages), + ?line {memory,BytesOther} = process_info(Pid, memory), + ?line {memory,BytesSelf} = process_info(self(), memory), + + io:format("Memory ~p: ~p\n", [Pid,BytesOther]), + io:format("Memory ~p (self): ~p\n", [self(),BytesSelf]), + + [Own,MsgA,MsgB,MsgC,MsgD,MsgE] = All, + + ?line Pid ! {self(),empty}, + ?line receive + empty -> ok + end, + ?line {messages,[]} = process_info(Pid, messages), + ?line Pid ! stop, + ok. + +process_info_other_dist_msg(Config) when is_list(Config) -> + %% + %% Check that process_info can handle messages that have not been + %% decoded yet. + %% + ?line {ok, Node} = start_node(Config), + ?line Self = self(), + ?line Pid = spawn_link(fun() -> other_process(Self) end), + ?line receive {go_ahead,Pid} -> ok end, + + ?line Own = {my,own,message}, + + ?line {messages,[Own]} = process_info(Pid, messages), + ?line Garbage = kb_128(), + ?line MsgA = {a,self(),Garbage}, + ?line MsgB = {b,self(),Garbage}, + ?line MsgC = {c,self(),Garbage}, + ?line MsgD = {d,self(),Garbage}, + ?line MsgE = {e,self(),Garbage}, + + %% We don't want the other process to decode messages itself + %% therefore we suspend it. + ?line true = erlang:suspend_process(Pid), + ?line spawn_link(Node, fun () -> + Pid ! MsgA, + Pid ! MsgB, + Pid ! MsgC, + Self ! check_abc + end), + ?line receive check_abc -> ok end, + ?line [{status,suspended}, + {messages,[Own,MsgA,MsgB,MsgC]}, + {status,suspended}]= process_info(Pid, [status,messages,status]), + ?line spawn_link(Node, fun () -> + Pid ! MsgD, + Pid ! MsgE, + Self ! check_de + end), + ?line receive check_de -> ok end, + ?line {messages,[Own,MsgA,MsgB,MsgC,MsgD,MsgE]=All} + = process_info(Pid, messages), + ?line true = erlang:resume_process(Pid), + ?line Pid ! {self(), get_all_messages}, + ?line receive + {all_messages, AllMsgs} -> + ?line All = AllMsgs + end, + ?line {messages,[]} = process_info(Pid, messages), + ?line Pid ! stop, + ?line stop_node(Node), + ?line ok. + + +other_process(Parent) -> + self() ! {my,own,message}, + Parent ! {go_ahead,self()}, + other_process_1(). + +other_process_1() -> + receive + {Parent,get_all_messages} -> + Parent ! {all_messages, get_all_messages()}, + other_process_1(); + {Parent,empty} -> + receive_all(), + Parent ! empty, + other_process_1(); + stop -> ok + end. + +get_all_messages() -> + get_all_messages([]). + +get_all_messages(Msgs) -> + receive + Msg -> + get_all_messages([Msg|Msgs]) + after 0 -> + lists:reverse(Msgs) + end. + +receive_all() -> + receive + _ -> receive_all() + after 0 -> ok + end. + +chk_pi_order([],[]) -> + ok; +chk_pi_order([{Arg, _}| Values], [Arg|Args]) -> + chk_pi_order(Values, Args). + +process_info_2_list(doc) -> + []; +process_info_2_list(suite) -> + []; +process_info_2_list(Config) when is_list(Config) -> + ?line Proc = spawn(fun () -> + receive after infinity -> ok end end), + register(process_SUITE_process_info_2_list1, self()), + register(process_SUITE_process_info_2_list2, Proc), + ?line erts_debug:set_internal_state(available_internal_state,true), + ?line AllArgs = erts_debug:get_internal_state(process_info_args), + ?line A1 = lists:sort(AllArgs) ++ [status] ++ lists:reverse(AllArgs), + + %% Verify that argument is accepted as single atom + ?line lists:foreach(fun (A) -> + ?line {A, _} = process_info(Proc, A), + ?line {A, _} = process_info(self(), A) + end, + A1), + + %% Verify that order is preserved + ?line ok = chk_pi_order(process_info(self(), A1), A1), + ?line ok = chk_pi_order(process_info(Proc, A1), A1), + + %% Small arg list + ?line A2 = [status, stack_size, trap_exit, priority], + ?line [{status, _}, {stack_size, _}, {trap_exit, _}, {priority, _}] + = process_info(Proc, A2), + ?line [{status, _}, {stack_size, _}, {trap_exit, _}, {priority, _}] + = process_info(self(), A2), + + %% Huge arg list (note values are shared) + ?line A3 = lists:duplicate(5000,backtrace), + ?line V3 = process_info(Proc, A3), + ?line 5000 = length(V3), + ?line lists:foreach(fun ({backtrace, _}) -> ok end, V3), + ?line ok. + +process_info_lock_reschedule(doc) -> + []; +process_info_lock_reschedule(suite) -> + []; +process_info_lock_reschedule(Config) when is_list(Config) -> + %% We need a process that is running and an item that requires + %% process_info to take the main process lock. + ?line Target1 = spawn_link(fun tok_loop/0), + ?line Name1 = process_info_lock_reschedule_running, + ?line register(Name1, Target1), + ?line Target2 = spawn_link(fun () -> receive after infinity -> ok end end), + ?line Name2 = process_info_lock_reschedule_waiting, + ?line register(Name2, Target2), + ?line PI = fun(_) -> + ?line erlang:yield(), + ?line [{registered_name, Name1}] + = process_info(Target1, [registered_name]), + ?line [{registered_name, Name2}] + = process_info(Target2, [registered_name]), + ?line erlang:yield(), + ?line {registered_name, Name1} + = process_info(Target1, registered_name), + ?line {registered_name, Name2} + = process_info(Target2, registered_name), + ?line erlang:yield(), + ?line [{registered_name, Name1}| _] + = process_info(Target1), + ?line [{registered_name, Name2}| _] + = process_info(Target2) + end, + ?line lists:foreach(PI, lists:seq(1,1000)), + %% Make sure Target1 still is willing to "tok loop" + ?line case process_info(Target1, status) of + {status, OkStatus} when OkStatus == runnable; + OkStatus == running; + OkStatus == garbage_collecting -> + ?line unlink(Target1), + ?line unlink(Target2), + ?line exit(Target1, bang), + ?line exit(Target2, bang), + ?line OkStatus; + {status, BadStatus} -> + ?line ?t:fail(BadStatus) + end. + +pi_loop(_Name, _Pid, 0) -> + ok; +pi_loop(Name, Pid, N) -> + {registered_name, Name} = process_info(Pid, registered_name), + pi_loop(Name, Pid, N-1). + +process_info_lock_reschedule2(doc) -> + []; +process_info_lock_reschedule2(suite) -> + []; +process_info_lock_reschedule2(Config) when is_list(Config) -> + ?line Parent = self(), + ?line Fun = fun () -> + receive {go, Name, Pid} -> ok end, + pi_loop(Name, Pid, 10000), + Parent ! {done, self()}, + receive after infinity -> ok end + end, + ?line P1 = spawn_link(Fun), + ?line N1 = process_info_lock_reschedule2_1, + ?line true = register(N1, P1), + ?line P2 = spawn_link(Fun), + ?line N2 = process_info_lock_reschedule2_2, + ?line true = register(N2, P2), + ?line P3 = spawn_link(Fun), + ?line N3 = process_info_lock_reschedule2_3, + ?line true = register(N3, P3), + ?line P4 = spawn_link(Fun), + ?line N4 = process_info_lock_reschedule2_4, + ?line true = register(N4, P4), + ?line P5 = spawn_link(Fun), + ?line N5 = process_info_lock_reschedule2_5, + ?line true = register(N5, P5), + ?line P6 = spawn_link(Fun), + ?line N6 = process_info_lock_reschedule2_6, + ?line true = register(N6, P6), + ?line P1 ! {go, N2, P2}, + ?line P2 ! {go, N1, P1}, + ?line P3 ! {go, N1, P1}, + ?line P4 ! {go, N1, P1}, + ?line P5 ! {go, N6, P6}, + ?line P6 ! {go, N5, P5}, + ?line receive {done, P1} -> ok end, + ?line receive {done, P2} -> ok end, + ?line receive {done, P3} -> ok end, + ?line receive {done, P4} -> ok end, + ?line receive {done, P5} -> ok end, + ?line receive {done, P6} -> ok end, + ?line unlink(P1), exit(P1, bang), + ?line unlink(P2), exit(P2, bang), + ?line unlink(P3), exit(P3, bang), + ?line unlink(P4), exit(P4, bang), + ?line unlink(P5), exit(P5, bang), + ?line unlink(P6), exit(P6, bang), + ?line ok. + +process_status_exiting(Config) when is_list(Config) -> + %% Make sure that erts_debug:get_internal_state({process_status,P}) + %% returns exiting if it is in status P_EXITING. + ?line erts_debug:set_internal_state(available_internal_state,true), + ?line Prio = process_flag(priority, max), + ?line P = spawn_opt(fun () -> receive after infinity -> ok end end, + [{priority, normal}]), + ?line erlang:yield(), + %% The tok_loop processes are here to make it hard for the exiting + %% process to be scheduled in for exit... + ?line TokLoops = lists:map(fun (_) -> + spawn_opt(fun tok_loop/0, + [link,{priority, high}]) + end, + lists:seq(1, erlang:system_info(schedulers_online))), + ?line exit(P, boom), + ?line wait_until( + fun () -> + exiting =:= erts_debug:get_internal_state({process_status,P}) + end), + ?line lists:foreach(fun (Tok) -> unlink(Tok), exit(Tok,bang) end, TokLoops), + ?line process_flag(priority, Prio), + ?line ok. + +otp_4725(Config) when is_list(Config) -> + ?line Tester = self(), + ?line Ref1 = make_ref(), + ?line Pid1 = spawn_opt(fun () -> + Tester ! {Ref1, process_info(self())}, + receive + Ref1 -> bye + end + end, + [link, + {priority, max}, + {fullsweep_after, 600}]), + ?line receive + {Ref1, ProcInfo1A} -> + ?line ProcInfo1B = process_info(Pid1), + ?line Pid1 ! Ref1, + ?line check_proc_infos(ProcInfo1A, ProcInfo1B) + end, + ?line Ref2 = make_ref(), + ?line Pid2 = spawn_opt(fun () -> + Tester ! {Ref2, process_info(self())}, + receive + Ref2 -> bye + end + end, + []), + ?line receive + {Ref2, ProcInfo2A} -> + ?line ProcInfo2B = process_info(Pid2), + ?line Pid2 ! Ref2, + ?line check_proc_infos(ProcInfo2A, ProcInfo2B) + end, + ?line ok. + +check_proc_infos(A, B) -> + ?line IC = lists:keysearch(initial_call, 1, A), + ?line IC = lists:keysearch(initial_call, 1, B), + + ?line L = lists:keysearch(links, 1, A), + ?line L = lists:keysearch(links, 1, B), + + ?line D = lists:keysearch(dictionary, 1, A), + ?line D = lists:keysearch(dictionary, 1, B), + + ?line TE = lists:keysearch(trap_exit, 1, A), + ?line TE = lists:keysearch(trap_exit, 1, B), + + ?line EH = lists:keysearch(error_handler, 1, A), + ?line EH = lists:keysearch(error_handler, 1, B), + + ?line P = lists:keysearch(priority, 1, A), + ?line P = lists:keysearch(priority, 1, B), + + ?line GL = lists:keysearch(group_leader, 1, A), + ?line GL = lists:keysearch(group_leader, 1, B), + + ?line GC = lists:keysearch(garbage_collection, 1, A), + ?line GC = lists:keysearch(garbage_collection, 1, B), + + ?line ok. + + +%% Dummies. + +start_spawner() -> + ok. + +stop_spawner() -> + ok. + +%% Tests erlang:bump_reductions/1. +bump_reductions(Config) when is_list(Config) -> + ?line erlang:garbage_collect(), + ?line receive after 1 -> ok end, % Clear reductions. + ?line {reductions,R1} = process_info(self(), reductions), + ?line true = erlang:bump_reductions(100), + ?line {reductions,R2} = process_info(self(), reductions), + ?line case R2-R1 of + Diff when Diff < 100 -> + ?line ok = io:format("R1 = ~w, R2 = ~w", [R1, R2]), + ?line test_server:fail({small_diff, Diff}); + Diff when Diff > 110 -> + ?line ok = io:format("R1 = ~w, R2 = ~w", [R1, R2]), + ?line test_server:fail({big_diff, Diff}); + Diff -> + io:format("~p\n", [Diff]), + ok + end, + + %% Make sure that a bignum reduction doesn't crash the emulator (32-bit CPU). + bump_big(R2, 16#08000000). + +bump_big(Prev, Limit) -> + ?line true = erlang:bump_reductions(100000), %Limited to CONTEXT_REDUCTIONS. + ?line case process_info(self(), reductions) of + {reductions,Big} when is_integer(Big), Big > Limit -> + ?line erlang:garbage_collect(), + ?line io:format("~p\n", [Big]); + {reductions,R} when is_integer(R), R > Prev -> + bump_big(R, Limit) + end, + ok. + +%% Priority 'low' should be mixed with 'normal' using a factor of +%% about 8. (OTP-2644) +low_prio(Config) when is_list(Config) -> + case erlang:system_info(schedulers_online) of + 1 -> + ?line ok = low_prio_test(Config); + _ -> + ?line erlang:system_flag(multi_scheduling, block), + ?line ok = low_prio_test(Config), + ?line erlang:system_flag(multi_scheduling, unblock), + ?line {comment, + "Test not written for SMP runtime system. " + "Multi scheduling blocked during test."} + end. + +low_prio_test(Config) when is_list(Config) -> + ?line process_flag(trap_exit, true), + ?line S = spawn_link(?MODULE, prio_server, [0, 0]), + ?line PCs = spawn_prio_clients(S, erlang:system_info(schedulers_online)), + ?line timer:sleep(2000), + ?line lists:foreach(fun (P) -> exit(P, kill) end, PCs), + ?line S ! exit, + ?line receive {'EXIT', S, {A, B}} -> check_prio(A, B) end, + ok. + +check_prio(A, B) -> + ?line Prop = A/B, + ?line ok = io:format("Low=~p, High=~p, Prop=~p\n", [A, B, Prop]), + + %% It isn't 1/8, it's more like 0.3, but let's check that + %% the low-prio processes get some little chance to run at all. + ?line true = (Prop < 1.0), + ?line true = (Prop > 1/32). + +prio_server(A, B) -> + receive + low -> + prio_server(A+1, B); + normal -> + prio_server(A, B+1); + exit -> + exit({A, B}) + end. + +spawn_prio_clients(_, 0) -> + []; +spawn_prio_clients(S, N) -> + [spawn_opt(?MODULE, prio_client, [S, normal], [link, {priority,normal}]), + spawn_opt(?MODULE, prio_client, [S, low], [link, {priority,low}]) + | spawn_prio_clients(S, N-1)]. + +prio_client(S, Prio) -> + S ! Prio, + prio_client(S, Prio). + +make_sub_binary(Bin) when is_binary(Bin) -> + {_,B} = split_binary(list_to_binary([0,1,3,Bin]), 3), + B; +make_sub_binary(List) -> + make_sub_binary(list_to_binary(List)). + +make_unaligned_sub_binary(Bin0) -> + Bin1 = <<0:3,Bin0/binary,31:5>>, + Sz = size(Bin0), + <<0:3,Bin:Sz/binary,31:5>> = id(Bin1), + Bin. + +yield(doc) -> + "Tests erlang:yield/1."; +yield(Config) when is_list(Config) -> + case catch erlang:system_info(modified_timing_level) of + Level when is_integer(Level) -> + {skipped, + "Modified timing (level " ++ integer_to_list(Level) + ++ ") is enabled. Testcase gets messed up by modfied " + "timing."}; + _ -> + MS = erlang:system_flag(multi_scheduling, block), + yield_test(), + erlang:system_flag(multi_scheduling, unblock), + case MS of + blocked -> + {comment, + "Multi-scheduling blocked during test. This test-case " + "was not written to work with multiple schedulers (the " + "yield2 test-case tests almost the same thing)."}; + _ -> + ok + end + end. + +yield_test() -> + ?line erlang:garbage_collect(), + ?line receive after 1 -> ok end, % Clear reductions. + ?line SC = schedcnt(start), + ?line {reductions, R1} = process_info(self(), reductions), + ?line {ok, true} = call_yield(middle), + ?line true = call_yield(final), + ?line true = call_yield(), + ?line true = apply(erlang, yield, []), + ?line {reductions, R2} = process_info(self(), reductions), + ?line Schedcnt = schedcnt(stop, SC), + ?line case {R2-R1, Schedcnt} of + {Diff, 4} when Diff < 30 -> + ?line ok = io:format("R1 = ~w, R2 = ~w, Schedcnt = ~w", + [R1, R2, Schedcnt]); + {Diff, _} -> + ?line ok = io:format("R1 = ~w, R2 = ~w, Schedcnt = ~w", + [R1, R2, Schedcnt]), + ?line test_server:fail({measurement_error, Diff, Schedcnt}) + end. + +call_yield() -> + erlang:yield(). + +call_yield(middle) -> + {ok, erlang:yield()}; +call_yield(final) -> + case self() of + Self when is_pid(Self) -> + ok + end, + erlang:yield(). + +schedcnt(start) -> + Ref = make_ref(), + Fun = + fun (F, Cnt) -> + receive + {Ref, Parent} -> + Parent ! {Ref, Cnt} + after 0 -> + erlang:yield(), + F(F, Cnt+1) + end + end, + Pid = spawn_link(fun () -> Fun(Fun, 0) end), + {Ref, Pid}. + +schedcnt(stop, {Ref, Pid}) when is_reference(Ref), is_pid(Pid) -> + Pid ! {Ref, self()}, + receive + {Ref, Cnt} -> + Cnt + end. + +yield2(doc) -> []; +yield2(suite) -> []; +yield2(Config) when is_list(Config) -> + ?line Me = self(), + ?line Go = make_ref(), + ?line RedDiff = make_ref(), + ?line Done = make_ref(), + ?line P = spawn(fun () -> + receive Go -> ok end, + {reductions, R1} = process_info(self(), reductions), + {ok, true} = call_yield(middle), + true = call_yield(final), + true = call_yield(), + true = apply(erlang, yield, []), + {reductions, R2} = process_info(self(), reductions), + Me ! {RedDiff, R2 - R1}, + exit(Done) + end), + ?line erlang:yield(), + + ?line 1 = erlang:trace(P, true, [running, procs, {tracer, self()}]), + + ?line P ! Go, + + %% receive Go -> ok end, + ?line {trace, P, in, _} = next_tmsg(P), + + %% {ok, true} = call_yield(middle), + ?line {trace, P, out, _} = next_tmsg(P), + ?line {trace, P, in, _} = next_tmsg(P), + + %% true = call_yield(final), + ?line {trace, P, out, _} = next_tmsg(P), + ?line {trace, P, in, _} = next_tmsg(P), + + %% true = call_yield(), + ?line {trace, P, out, _} = next_tmsg(P), + ?line {trace, P, in, _} = next_tmsg(P), + + %% true = apply(erlang, yield, []), + ?line {trace, P, out, _} = next_tmsg(P), + ?line {trace, P, in, _} = next_tmsg(P), + + %% exit(Done) + ?line {trace, P, exit, Done} = next_tmsg(P), + + + ?line receive + {RedDiff, Reductions} when Reductions < 30, Reductions > 0 -> + io:format("Reductions = ~p~n", [Reductions]), + ?line ok; + {RedDiff, Reductions} -> + ?line ?t:fail({unexpected_reduction_count, Reductions}) + end, + + ?line none = next_tmsg(P), + + ?line ok. + +next_tmsg(Pid) -> + receive + TMsg when is_tuple(TMsg), + element(1, TMsg) == trace, + element(2, TMsg) == Pid -> + TMsg + after 100 -> + none + end. + +%% Test that bad arguments to register/2 cause an exception. +bad_register(Config) when is_list(Config) -> + Name = a_long_and_unused_name, + + ?line {'EXIT',{badarg,_}} = (catch register({bad,name}, self())), + ?line fail_register(undefined, self()), + ?line fail_register([bad,name], self()), + + ?line {Dead,Mref} = spawn_monitor(fun() -> true end), + receive + {'DOWN',Mref,process,Dead,_} -> ok + end, + ?line fail_register(Name, Dead), + ?line fail_register(Name, make_ref()), + ?line fail_register(Name, []), + ?line fail_register(Name, {bad,process}), + ?line fail_register(Name, <<>>), + ok. + +fail_register(Name, Process) -> + {'EXIT',{badarg,_}} = (catch register(Name, Process)), + {'EXIT',{badarg,_}} = (catch Name ! anything_goes), + ok. + +garbage_collect(doc) -> []; +garbage_collect(suite) -> []; +garbage_collect(Config) when is_list(Config) -> + ?line Prio = process_flag(priority, high), + ?line true = erlang:garbage_collect(), + ?line TokLoopers = lists:map(fun (_) -> + spawn_opt(fun tok_loop/0, + [{priority, low}, link]) + end, + lists:seq(1, 10)), + ?line lists:foreach(fun (Pid) -> + ?line Mon = erlang:monitor(process, Pid), + ?line DownBefore = receive + {'DOWN', Mon, _, _, _} -> + ?line true + after 0 -> + ?line false + end, + ?line GC = erlang:garbage_collect(Pid), + ?line DownAfter = receive + {'DOWN', Mon, _, _, _} -> + ?line true + after 0 -> + ?line false + end, + ?line true = erlang:demonitor(Mon), + ?line case {DownBefore, DownAfter} of + {true, _} -> ?line false = GC; + {false, false} -> ?line true = GC; + _ -> ?line GC + end + end, + processes()), + ?line lists:foreach(fun (Pid) -> + unlink(Pid), + exit(Pid, bang) + end, TokLoopers), + ?line process_flag(priority, Prio), + ?line ok. + +process_info_messages(doc) -> + ["This used to cause the nofrag emulator to dump core"]; +process_info_messages(suite) -> + []; +process_info_messages(Config) when is_list(Config) -> + ?line process_info_messages_test(), + ?line ok. + +process_info_messages_loop(0) -> ok; +process_info_messages_loop(N) -> process_info_messages_loop(N-1). + +process_info_messages_send_my_msgs_to(Rcvr) -> + receive + Msg -> + Rcvr ! Msg, + process_info_messages_send_my_msgs_to(Rcvr) + after 0 -> + ok + end. + +process_info_messages_test() -> + ?line Go = make_ref(), + ?line Done = make_ref(), + ?line Rcvr = self(), + ?line Rcvr2 = spawn_link(fun () -> + receive {Go, Rcvr} -> ok end, + garbage_collect(), + Rcvr ! {Done, self()} + end), + ?line Sndrs = lists:map( + fun (_) -> + spawn_link(fun () -> + Rcvr ! {Go, self()}, + receive {Go, Rcvr} -> ok end, + BigData = lists:seq(1, 1000), + Rcvr ! BigData, + Rcvr ! BigData, + Rcvr ! BigData, + Rcvr ! {Done, self()} + end) + end, + lists:seq(1, 10)), + ?line lists:foreach(fun (Sndr) -> receive {Go, Sndr} -> ok end end, + Sndrs), + ?line garbage_collect(), + ?line erlang:yield(), + ?line lists:foreach(fun (Sndr) -> Sndr ! {Go, self()} end, Sndrs), + ?line process_info_messages_loop(100000000), + ?line Msgs = process_info(self(), messages), + ?line lists:foreach(fun (Sndr) -> receive {Done, Sndr} -> ok end end, + Sndrs), + ?line garbage_collect(), + ?line Rcvr2 ! Msgs, + ?line process_info_messages_send_my_msgs_to(Rcvr2), + ?line Rcvr2 ! {Go, self()}, + ?line garbage_collect(), + ?line receive {Done, Rcvr2} -> ok end, + ?line Msgs. + +chk_badarg(Fun) -> + try Fun(), exit(no_badarg) catch error:badarg -> ok end. + +process_flag_badarg(doc) -> + []; +process_flag_badarg(suite) -> + []; +process_flag_badarg(Config) when is_list(Config) -> + ?line chk_badarg(fun () -> process_flag(gurka, banan) end), + ?line chk_badarg(fun () -> process_flag(trap_exit, gurka) end), + ?line chk_badarg(fun () -> process_flag(error_handler, 1) end), + ?line chk_badarg(fun () -> process_flag(min_heap_size, gurka) end), + ?line chk_badarg(fun () -> process_flag(priority, 4711) end), + ?line chk_badarg(fun () -> process_flag(save_calls, hmmm) end), + ?line P= spawn_link(fun () -> receive die -> ok end end), + ?line chk_badarg(fun () -> process_flag(P, save_calls, hmmm) end), + ?line chk_badarg(fun () -> process_flag(gurka, save_calls, hmmm) end), + ?line P ! die, + ?line ok. + +-include_lib("stdlib/include/ms_transform.hrl"). + +otp_6237(doc) -> []; +otp_6237(suite) -> []; +otp_6237(Config) when is_list(Config) -> + ?line Slctrs = lists:map(fun (_) -> + spawn_link(fun () -> + otp_6237_select_loop() + end) + end, + lists:seq(1,5)), + ?line lists:foreach(fun (_) -> otp_6237_test() end, lists:seq(1, 100)), + ?line lists:foreach(fun (S) -> unlink(S),exit(S, kill) end, Slctrs), + ?line ok. + +otp_6237_test() -> + ?line Parent = self(), + ?line Inited = make_ref(), + ?line Die = make_ref(), + ?line Pid = spawn_link(fun () -> + register(otp_6237,self()), + otp_6237 = ets:new(otp_6237, + [named_table, + ordered_set]), + ets:insert(otp_6237, + [{I,I} + || I <- lists:seq(1, 100)]), + %% Inserting a lot of bif timers + %% increase the possibility that + %% the test will fail when the + %% original cleanup order is used + lists:foreach( + fun (_) -> + erlang:send_after(1000000, + self(), + {a,b,c}) + end, + lists:seq(1,1000)), + Parent ! Inited, + receive Die -> bye end + end), + ?line receive + Inited -> ?line ok + end, + ?line Pid ! Die, + otp_6237_whereis_loop(). + +otp_6237_whereis_loop() -> + ?line case whereis(otp_6237) of + undefined -> + ?line otp_6237 = ets:new(otp_6237, + [named_table,ordered_set]), + ?line ets:delete(otp_6237), + ?line ok; + _ -> + ?line otp_6237_whereis_loop() + end. + +otp_6237_select_loop() -> + catch ets:select(otp_6237, ets:fun2ms(fun({K, does_not_exist}) -> K end)), + otp_6237_select_loop(). + + +processes_bif(doc) -> + []; +processes_bif(suite) -> + [processes_large_tab, + processes_default_tab, + processes_small_tab, + processes_this_tab, + processes_last_call_trap, + processes_apply_trap, + processes_gc_trap, + processes_term_proc_list]. + +-define(NoTestProcs, 10000). +-record(processes_bif_info, {min_start_reds, + tab_chunks, + tab_chunks_size, + tab_indices_per_red, + free_term_proc_reds, + term_procs_per_red, + term_procs_max_reds, + conses_per_red, + debug_level}). + +processes_large_tab(doc) -> + []; +processes_large_tab(suite) -> + []; +processes_large_tab(Config) when is_list(Config) -> + ?line enable_internal_state(), + ?line MaxDbgLvl = 20, + ?line MinProcTabSize = 2*(1 bsl 15), + ?line ProcTabSize0 = 1000000, + ?line ProcTabSize1 = case {erlang:system_info(schedulers_online), + erlang:system_info(logical_processors)} of + {Schdlrs, Cpus} when is_integer(Cpus), + Schdlrs =< Cpus -> + ProcTabSize0; + _ -> + ProcTabSize0 div 4 + end, + ?line ProcTabSize2 = case erlang:system_info(debug_compiled) of + true -> ProcTabSize1 - 500000; + false -> ProcTabSize1 + end, + %% With high debug levels this test takes so long time that + %% the connection times out; therefore, shrink the test on + %% high debug levels. + ?line DbgLvl = case erts_debug:get_internal_state(processes_bif_info) of + #processes_bif_info{debug_level = Lvl} when Lvl > MaxDbgLvl -> + 20; + #processes_bif_info{debug_level = Lvl} when Lvl < 0 -> + ?line ?t:fail({debug_level, Lvl}); + #processes_bif_info{debug_level = Lvl} -> + Lvl + end, + ?line ProcTabSize3 = ProcTabSize2 - (1300000 * DbgLvl div MaxDbgLvl), + ?line ProcTabSize = case ProcTabSize3 < MinProcTabSize of + true -> MinProcTabSize; + false -> ProcTabSize3 + end, + ?line {ok, LargeNode} = start_node(Config, + "+P " ++ integer_to_list(ProcTabSize)), + ?line Res = rpc:call(LargeNode, ?MODULE, processes_bif_test, []), + ?line case rpc:call(LargeNode, + erts_debug, + get_internal_state, + [processes_bif_info]) of + #processes_bif_info{tab_chunks = Chunks} when is_integer(Chunks), + Chunks > 1 -> ok; + PBInfo -> ?t:fail(PBInfo) + end, + ?line stop_node(LargeNode), + ?line chk_processes_bif_test_res(Res). + +processes_default_tab(doc) -> + []; +processes_default_tab(suite) -> + []; +processes_default_tab(Config) when is_list(Config) -> + ?line {ok, DefaultNode} = start_node(Config, ""), + ?line Res = rpc:call(DefaultNode, ?MODULE, processes_bif_test, []), + ?line stop_node(DefaultNode), + ?line chk_processes_bif_test_res(Res). + +processes_small_tab(doc) -> + []; +processes_small_tab(suite) -> + []; +processes_small_tab(Config) when is_list(Config) -> + ?line {ok, SmallNode} = start_node(Config, "+P 500"), + ?line Res = rpc:call(SmallNode, ?MODULE, processes_bif_test, []), + ?line PBInfo = rpc:call(SmallNode, + erts_debug, + get_internal_state, + [processes_bif_info]), + ?line stop_node(SmallNode), + ?line 1 = PBInfo#processes_bif_info.tab_chunks, + ?line chk_processes_bif_test_res(Res). + +processes_this_tab(doc) -> + []; +processes_this_tab(suite) -> + []; +processes_this_tab(Config) when is_list(Config) -> + ?line chk_processes_bif_test_res(processes_bif_test()). + +chk_processes_bif_test_res(ok) -> ok; +chk_processes_bif_test_res({comment, _} = Comment) -> Comment; +chk_processes_bif_test_res(Failure) -> ?t:fail(Failure). + +print_processes_bif_info(#processes_bif_info{min_start_reds = MinStartReds, + tab_chunks = TabChunks, + tab_chunks_size = TabChunksSize, + tab_indices_per_red = TabIndPerRed, + free_term_proc_reds = FreeTPReds, + term_procs_per_red = TPPerRed, + term_procs_max_reds = TPMaxReds, + conses_per_red = ConsesPerRed, + debug_level = DbgLvl}) -> + ?t:format("processes/0 bif info on node ~p:~n" + "Min start reductions = ~p~n" + "Process table chunks = ~p~n" + "Process table chunks size = ~p~n" + "Process table indices per reduction = ~p~n" + "Reduction cost for free() on terminated process struct = ~p~n" + "Inspect terminated processes per reduction = ~p~n" + "Max reductions during inspection of terminated processes = ~p~n" + "Create cons-cells per reduction = ~p~n" + "Debug level = ~p~n", + [node(), + MinStartReds, + TabChunks, + TabChunksSize, + TabIndPerRed, + FreeTPReds, + TPPerRed, + TPMaxReds, + ConsesPerRed, + DbgLvl]). + +processes_bif_cleaner() -> + receive {'EXIT', _, _} -> ok end, + processes_bif_cleaner(). + +spawn_initial_hangarounds(Cleaner) -> + TabSz = erlang:system_info(process_limit), + spawn_initial_hangarounds(Cleaner, + TabSz, + TabSz*2, + 0, + []). + +processes_unexpected_result(CorrectProcs, Procs) -> + ProcInfo = [registered_name, + initial_call, + current_function, + status, + priority], + MissingProcs = CorrectProcs -- Procs, + ?t:format("Missing processes: ~p", + [lists:map(fun (Pid) -> + [{pid, Pid} + | case process_info(Pid, ProcInfo) of + undefined -> []; + Res -> Res + end] + end, + MissingProcs)]), + SuperfluousProcs = Procs -- CorrectProcs, + ?t:format("Superfluous processes: ~p", + [lists:map(fun (Pid) -> + [{pid, Pid} + | case process_info(Pid, ProcInfo) of + undefined -> []; + Res -> Res + end] + end, + SuperfluousProcs)]), + ?t:fail(unexpected_result). + +hangaround(Cleaner, Type) -> + %% Type is only used to distinguish different processes from + %% when doing process_info + try link(Cleaner) catch error:Reason -> exit(Reason) end, + receive after infinity -> ok end, + exit(Type). + +spawn_initial_hangarounds(_Cleaner, NP, Max, Len, HAs) when NP > Max -> + {Len, HAs}; +spawn_initial_hangarounds(Cleaner, NP, Max, Len, HAs) -> + erts_debug:set_internal_state(next_pid,NP), + HA1 = spawn_opt(?MODULE, hangaround, [Cleaner, initial_hangaround], + [{priority, low}]), + HA2 = spawn_opt(?MODULE, hangaround, [Cleaner, initial_hangaround], + [{priority, normal}]), + HA3 = spawn_opt(?MODULE, hangaround, [Cleaner, initial_hangaround], + [{priority, high}]), + spawn_initial_hangarounds(Cleaner, NP+30, Max, Len+3, [HA1,HA2,HA3|HAs]). + +do_processes(WantReds) -> + erts_debug:set_internal_state(reds_left, WantReds), + processes(). + +processes_bif_test() -> + ?line Tester = self(), + ?line enable_internal_state(), + ?line PBInfo = erts_debug:get_internal_state(processes_bif_info), + ?line print_processes_bif_info(PBInfo), + ?line WantReds = PBInfo#processes_bif_info.min_start_reds + 10, + ?line WillTrap = case PBInfo of + #processes_bif_info{tab_chunks = 1} -> + false; + #processes_bif_info{tab_chunks = Chunks, + tab_chunks_size = ChunksSize, + tab_indices_per_red = IndiciesPerRed + } -> + Chunks*ChunksSize >= IndiciesPerRed*WantReds + end, + ?line Processes = fun () -> + erts_debug:set_internal_state(reds_left,WantReds), + processes() + end, + + ?line ok = do_processes_bif_test(WantReds, WillTrap, Processes), + + case WillTrap of + false -> + ok; + true -> + %% Do it again with a process suspended while + %% in the processes/0 bif. + ?line erlang:system_flag(multi_scheduling, block), + ?line Suspendee = spawn_link(fun () -> + Tester ! {suspend_me, self()}, + Tester ! {self(), + done, + hd(Processes())}, + receive + after infinity -> + ok + end + end), + ?line receive {suspend_me, Suspendee} -> ok end, + ?line erlang:suspend_process(Suspendee), + ?line erlang:system_flag(multi_scheduling, unblock), + + ?line [{status,suspended}, + {current_function,{erlang,processes_trap,2}}] + = process_info(Suspendee, [status, current_function]), + + ?line ok = do_processes_bif_test(WantReds, WillTrap, Processes), + + ?line erlang:resume_process(Suspendee), + ?line receive {Suspendee, done, _} -> ok end, + ?line unlink(Suspendee), + ?line exit(Suspendee, bang) + end, + case get(processes_bif_testcase_comment) of + undefined -> ?line ok; + Comment -> ?line {comment, Comment} + end. + +do_processes_bif_test(WantReds, DieTest, Processes) -> + ?line Tester = self(), + ?line SpawnProcesses = fun (Prio) -> + spawn_opt(?MODULE, + do_processes, + [WantReds], + [link, {priority, Prio}]) + end, + ?line Cleaner = spawn_link(fun () -> + process_flag(trap_exit, true), + Tester ! {cleaner_alive, self()}, + processes_bif_cleaner() + end), + ?line receive {cleaner_alive, Cleaner} -> ok end, + try + ?line DoIt = make_ref(), + ?line GetGoing = make_ref(), + ?line {NoTestProcs, TestProcs} = spawn_initial_hangarounds(Cleaner), + ?line ?t:format("Testing with ~p processes~n", [NoTestProcs]), + ?line SpawnHangAround = fun () -> + spawn(?MODULE, + hangaround, + [Cleaner, new_hangaround]) + end, + ?line Killer = spawn_opt(fun () -> + Splt = NoTestProcs div 10, + {TP1, TP23} = lists:split(Splt, + TestProcs), + {TP2, TP3} = lists:split(Splt, TP23), + erlang:system_flag(multi_scheduling, + block), + Tester ! DoIt, + receive GetGoing -> ok end, + erlang:system_flag(multi_scheduling, + unblock), + SpawnProcesses(high), + lists:foreach( + fun (P) -> + SpawnHangAround(), + exit(P, bang) + end, + TP1), + SpawnProcesses(high), + erlang:yield(), + lists:foreach( + fun (P) -> + SpawnHangAround(), + exit(P, bang) + end, + TP2), + SpawnProcesses(high), + lists:foreach( + fun (P) -> + SpawnHangAround(), + exit(P, bang) + end, + TP3) + end, + [{priority, high}, link]), + ?line receive DoIt -> ok end, + ?line process_flag(priority, low), + ?line SpawnProcesses(low), + ?line erlang:yield(), + ?line process_flag(priority, normal), + ?line CorrectProcs0 = erts_debug:get_internal_state(processes), + ?line Killer ! GetGoing, + ?line erts_debug:set_internal_state(reds_left, WantReds), + ?line Procs0 = processes(), + ?line Procs = lists:sort(Procs0), + ?line CorrectProcs = lists:sort(CorrectProcs0), + ?line LengthCorrectProcs = length(CorrectProcs), + ?line ?t:format("~p = length(CorrectProcs)~n", [LengthCorrectProcs]), + ?line true = LengthCorrectProcs > NoTestProcs, + ?line case CorrectProcs =:= Procs of + true -> + ?line ok; + false -> + ?line processes_unexpected_result(CorrectProcs, Procs) + end, + ?line unlink(Killer), + ?line exit(Killer, bang) + after + unlink(Cleaner), + exit(Cleaner, kill), + %% Wait for the system to recover to a normal state... + wait_until_system_recover() + end, + ?line do_processes_bif_die_test(DieTest, Processes), + ?line ok. + + +do_processes_bif_die_test(false, _Processes) -> + ?line ?t:format("Skipping test killing process executing processes/0~n",[]), + ?line ok; +do_processes_bif_die_test(true, Processes) -> + ?line do_processes_bif_die_test(5, Processes); +do_processes_bif_die_test(N, Processes) -> + ?line ?t:format("Doing test killing process executing processes/0~n",[]), + try + ?line Tester = self(), + ?line Oooh_Nooooooo = make_ref(), + ?line {_, DieWhileDoingMon} = erlang:spawn_monitor( + fun () -> + Victim = self(), + spawn_opt( + fun () -> + exit(Victim, got_him) + end, + [link, + {priority, max}]), + Tester ! {Oooh_Nooooooo, + hd(Processes())}, + exit(ohhhh_nooooo) + end), + ?line receive + {'DOWN', DieWhileDoingMon, _, _, Reason} -> + case Reason of + got_him -> ok; + _ -> throw({kill_in_trap, Reason}) + end + end, + ?line receive + {Oooh_Nooooooo, _} -> + ?line throw({kill_in_trap, 'Oooh_Nooooooo'}) + after 0 -> + ?line ok + end, + ?line PrcsCllrsSeqLen = 2*erlang:system_info(schedulers_online), + ?line PrcsCllrsSeq = lists:seq(1, PrcsCllrsSeqLen), + ?line ProcsCallers = lists:map( + fun (_) -> + spawn_link( + fun () -> + Tester ! hd(Processes()) + end) + end, + PrcsCllrsSeq), + ?line erlang:yield(), + {ProcsCallers1, ProcsCallers2} = lists:split(PrcsCllrsSeqLen div 2, + ProcsCallers), + ?line process_flag(priority, high), + ?line lists:foreach( + fun (P) -> + unlink(P), + exit(P, bang) + end, + lists:reverse(ProcsCallers2) ++ ProcsCallers1), + ?line process_flag(priority, normal), + ?line ok + catch + throw:{kill_in_trap, R} when N > 0 -> + ?t:format("Failed to kill in trap: ~p~n", [R]), + ?t:format("Trying again~p~n", []), + do_processes_bif_die_test(N-1, Processes) + end. + + +wait_until_system_recover() -> + %% If system hasn't recovered after 10 seconds we give up + Tmr = erlang:start_timer(10000, self(), no_more_wait), + wait_until_system_recover(Tmr). + +wait_until_system_recover(Tmr) -> + try + lists:foreach(fun (P) when P == self() -> + ok; + (P) -> + case process_info(P, initial_call) of + {initial_call,{?MODULE, _, _}} -> + throw(wait); + {initial_call,{_, _, _}} -> + ok; + undefined -> + ok + end + end, + processes()) + catch + throw:wait -> + receive + {timeout, Tmr, _} -> + Comment = "WARNING: Test processes still hanging around!", + ?t:format("~s~n", [Comment]), + put(processes_bif_testcase_comment, Comment), + lists:foreach( + fun (P) when P == self() -> + ok; + (P) -> + case process_info(P, initial_call) of + {initial_call,{?MODULE, _, _} = MFA} -> + ?t:format("~p ~p~n", [P, MFA]); + {initial_call,{_, _, _}} -> + ok; + undefined -> + ok + end + end, + processes()) + after 100 -> + wait_until_system_recover(Tmr) + end + end, + erlang:cancel_timer(Tmr), + receive {timeout, Tmr, _} -> ok after 0 -> ok end, + ok. + +processes_last_call_trap(doc) -> + []; +processes_last_call_trap(suite) -> + []; +processes_last_call_trap(Config) when is_list(Config) -> + ?line enable_internal_state(), + ?line Processes = fun () -> processes() end, + ?line PBInfo = erts_debug:get_internal_state(processes_bif_info), + ?line print_processes_bif_info(PBInfo), + ?line WantReds = case PBInfo#processes_bif_info.min_start_reds of + R when R > 10 -> R - 1; + _R -> 9 + end, + ?line lists:foreach(fun (_) -> + ?line erts_debug:set_internal_state(reds_left, + WantReds), + Processes(), + ?line erts_debug:set_internal_state(reds_left, + WantReds), + my_processes() + end, + lists:seq(1,100)). + +my_processes() -> + processes(). + +processes_apply_trap(doc) -> + []; +processes_apply_trap(suite) -> + []; +processes_apply_trap(Config) when is_list(Config) -> + ?line enable_internal_state(), + ?line PBInfo = erts_debug:get_internal_state(processes_bif_info), + ?line print_processes_bif_info(PBInfo), + ?line WantReds = case PBInfo#processes_bif_info.min_start_reds of + R when R > 10 -> R - 1; + _R -> 9 + end, + ?line lists:foreach(fun (_) -> + ?line erts_debug:set_internal_state(reds_left, + WantReds), + ?line apply(erlang, processes, []) + end, + lists:seq(1,100)). + +processes_gc_trap(doc) -> + []; +processes_gc_trap(suite) -> + []; +processes_gc_trap(Config) when is_list(Config) -> + ?line Tester = self(), + ?line enable_internal_state(), + ?line PBInfo = erts_debug:get_internal_state(processes_bif_info), + ?line print_processes_bif_info(PBInfo), + ?line WantReds = PBInfo#processes_bif_info.min_start_reds + 10, + ?line Processes = fun () -> + erts_debug:set_internal_state(reds_left,WantReds), + processes() + end, + + ?line erlang:system_flag(multi_scheduling, block), + ?line Suspendee = spawn_link(fun () -> + Tester ! {suspend_me, self()}, + Tester ! {self(), + done, + hd(Processes())}, + receive after infinity -> ok end + end), + ?line receive {suspend_me, Suspendee} -> ok end, + ?line erlang:suspend_process(Suspendee), + ?line erlang:system_flag(multi_scheduling, unblock), + + ?line [{status,suspended}, {current_function,{erlang,processes_trap,2}}] + = process_info(Suspendee, [status, current_function]), + + ?line erlang:garbage_collect(Suspendee), + ?line erlang:garbage_collect(Suspendee), + + ?line erlang:resume_process(Suspendee), + ?line receive {Suspendee, done, _} -> ok end, + ?line erlang:garbage_collect(Suspendee), + ?line erlang:garbage_collect(Suspendee), + + ?line unlink(Suspendee), + ?line exit(Suspendee, bang), + ?line ok. + + +processes_term_proc_list(doc) -> + []; +processes_term_proc_list(suite) -> + []; +processes_term_proc_list(Config) when is_list(Config) -> + ?line Tester = self(), + ?line as_expected = processes_term_proc_list_test(false), + ?line {ok, Node} = start_node(Config, "+Mis true"), + ?line RT = spawn_link(Node, + fun () -> + receive after 1000 -> ok end, + processes_term_proc_list_test(false), + Tester ! {it_worked, self()} + end), + ?line receive {it_worked, RT} -> ok end, + ?line stop_node(Node), + ?line ok. + +-define(CHK_TERM_PROC_LIST(MC, XB), + chk_term_proc_list(?LINE, MC, XB)). + +chk_term_proc_list(Line, MustChk, ExpectBlks) -> + case {MustChk, instrument:memory_status(types)} of + {false, false} -> + not_enabled; + {_, MS} -> + {value, + {processes_term_proc_el, + DL}} = lists:keysearch(processes_term_proc_el, 1, MS), + case lists:keysearch(blocks, 1, DL) of + {value, {blocks, ExpectBlks, _, _}} -> + ok; + {value, {blocks, Blks, _, _}} -> + exit({line, Line, + mismatch, expected, ExpectBlks, actual, Blks}); + Unexpected -> + exit(Unexpected) + end + end, + ok. + +processes_term_proc_list_test(MustChk) -> + ?line Tester = self(), + ?line enable_internal_state(), + ?line PBInfo = erts_debug:get_internal_state(processes_bif_info), + ?line print_processes_bif_info(PBInfo), + ?line WantReds = PBInfo#processes_bif_info.min_start_reds + 10, + ?line #processes_bif_info{tab_chunks = Chunks, + tab_chunks_size = ChunksSize, + tab_indices_per_red = IndiciesPerRed + } = PBInfo, + ?line true = Chunks > 1, + ?line true = Chunks*ChunksSize >= IndiciesPerRed*WantReds, + ?line Processes = fun () -> + erts_debug:set_internal_state(reds_left, + WantReds), + processes() + end, + ?line Exit = fun (P) -> + unlink(P), + exit(P, bang), + wait_until( + fun () -> + not lists:member( + P, + erts_debug:get_internal_state( + processes)) + end) + end, + ?line SpawnSuspendProcessesProc + = fun () -> + erlang:system_flag(multi_scheduling, block), + P = spawn_link(fun () -> + Tester ! {suspend_me, self()}, + Tester ! {self(), + done, + hd(Processes())}, + receive after infinity -> ok end + end), + receive {suspend_me, P} -> ok end, + erlang:suspend_process(P), + erlang:system_flag(multi_scheduling, unblock), + [{status,suspended}, + {current_function,{erlang,processes_trap,2}}] + = process_info(P, [status, current_function]), + P + end, + ?line ResumeProcessesProc = fun (P) -> + erlang:resume_process(P), + receive {P, done, _} -> ok end + end, + ?line ?CHK_TERM_PROC_LIST(MustChk, 0), + ?line HangAround = fun () -> receive after infinity -> ok end end, + ?line HA1 = spawn_link(HangAround), + ?line HA2 = spawn_link(HangAround), + ?line HA3 = spawn_link(HangAround), + ?line S1 = SpawnSuspendProcessesProc(), + ?line ?CHK_TERM_PROC_LIST(MustChk, 1), + ?line Exit(HA1), + ?line ?CHK_TERM_PROC_LIST(MustChk, 2), + ?line S2 = SpawnSuspendProcessesProc(), + ?line ?CHK_TERM_PROC_LIST(MustChk, 3), + ?line S3 = SpawnSuspendProcessesProc(), + ?line ?CHK_TERM_PROC_LIST(MustChk, 4), + ?line Exit(HA2), + ?line ?CHK_TERM_PROC_LIST(MustChk, 5), + ?line S4 = SpawnSuspendProcessesProc(), + ?line ?CHK_TERM_PROC_LIST(MustChk, 6), + ?line Exit(HA3), + ?line ?CHK_TERM_PROC_LIST(MustChk, 7), + ?line ResumeProcessesProc(S1), + ?line ?CHK_TERM_PROC_LIST(MustChk, 5), + ?line ResumeProcessesProc(S3), + ?line ?CHK_TERM_PROC_LIST(MustChk, 4), + ?line ResumeProcessesProc(S4), + ?line ?CHK_TERM_PROC_LIST(MustChk, 3), + ?line ResumeProcessesProc(S2), + ?line ?CHK_TERM_PROC_LIST(MustChk, 0), + ?line Exit(S1), + ?line Exit(S2), + ?line Exit(S3), + ?line Exit(S4), + + + ?line HA4 = spawn_link(HangAround), + ?line HA5 = spawn_link(HangAround), + ?line HA6 = spawn_link(HangAround), + ?line S5 = SpawnSuspendProcessesProc(), + ?line ?CHK_TERM_PROC_LIST(MustChk, 1), + ?line Exit(HA4), + ?line ?CHK_TERM_PROC_LIST(MustChk, 2), + ?line S6 = SpawnSuspendProcessesProc(), + ?line ?CHK_TERM_PROC_LIST(MustChk, 3), + ?line Exit(HA5), + ?line ?CHK_TERM_PROC_LIST(MustChk, 4), + ?line S7 = SpawnSuspendProcessesProc(), + ?line ?CHK_TERM_PROC_LIST(MustChk, 5), + ?line Exit(HA6), + ?line ?CHK_TERM_PROC_LIST(MustChk, 6), + ?line S8 = SpawnSuspendProcessesProc(), + ?line ?CHK_TERM_PROC_LIST(MustChk, 7), + + ?line erlang:system_flag(multi_scheduling, block), + ?line Exit(S8), + ?line ?CHK_TERM_PROC_LIST(MustChk, 7), + ?line Exit(S5), + ?line ?CHK_TERM_PROC_LIST(MustChk, 6), + ?line Exit(S7), + ?line ?CHK_TERM_PROC_LIST(MustChk, 6), + ?line Exit(S6), + ?line ?CHK_TERM_PROC_LIST(MustChk, 0), + ?line erlang:system_flag(multi_scheduling, unblock), + ?line as_expected. + +otp_7738(doc) -> + []; +otp_7738(suite) -> + [otp_7738_waiting, otp_7738_suspended, otp_7738_resume]. + +otp_7738_waiting(doc) -> + []; +otp_7738_waiting(suite) -> + []; +otp_7738_waiting(Config) when is_list(Config) -> + ?line otp_7738_test(waiting). + +otp_7738_suspended(doc) -> + []; +otp_7738_suspended(suite) -> + []; +otp_7738_suspended(Config) when is_list(Config) -> + ?line otp_7738_test(suspended). + +otp_7738_resume(doc) -> + []; +otp_7738_resume(suite) -> + []; +otp_7738_resume(Config) when is_list(Config) -> + ?line otp_7738_test(resume). + +otp_7738_test(Type) -> + ?line T = self(), + ?line S = spawn_link(fun () -> + receive + {suspend, Suspendee} -> + erlang:suspend_process(Suspendee), + T ! {suspended, Suspendee}, + receive + after 10 -> + erlang:resume_process(Suspendee), + Suspendee ! wake_up + end; + {send, To, Msg} -> + receive after 10 -> ok end, + To ! Msg + end + end), + ?line R = spawn_link(fun () -> + X = lists:seq(1, 20000000), + T ! {initialized, self()}, + ?line case Type of + _ when Type == suspended; + Type == waiting -> + receive _ -> ok end; + _ when Type == resume -> + Receive = fun (F) -> + receive + _ -> + ok + after 0 -> + F(F) + end + end, + Receive(Receive) + end, + T ! {woke_up, self()}, + id(X) + end), + ?line receive {initialized, R} -> ok end, + ?line receive after 10 -> ok end, + ?line case Type of + suspended -> + ?line erlang:suspend_process(R), + ?line S ! {send, R, wake_up}; + waiting -> + ?line S ! {send, R, wake_up}; + resume -> + ?line S ! {suspend, R}, + ?line receive {suspended, R} -> ok end + end, + ?line erlang:garbage_collect(R), + ?line case Type of + suspended -> + ?line erlang:resume_process(R); + _ -> + ?line ok + end, + ?line receive + {woke_up, R} -> + ?line ok + after 2000 -> + ?line I = process_info(R, [status, message_queue_len]), + ?line ?t:format("~p~n", [I]), + ?line ?t:fail(no_progress) + end, + ?line ok. + +%% Internal functions + +wait_until(Fun) -> + case Fun() of + true -> true; + false -> receive after 10 -> wait_until(Fun) end + end. + +tok_loop() -> + tok_loop(hej). + +tok_loop(hej) -> + tok_loop(hopp); +tok_loop(hopp) -> + tok_loop(hej). + +id(I) -> I. + +start_node(Config) -> + start_node(Config, ""). + +start_node(Config, Args) when is_list(Config) -> + ?line Pa = filename:dirname(code:which(?MODULE)), + ?line {A, B, C} = now(), + ?line Name = list_to_atom(atom_to_list(?MODULE) + ++ "-" + ++ atom_to_list(?config(testcase, Config)) + ++ "-" + ++ integer_to_list(A) + ++ "-" + ++ integer_to_list(B) + ++ "-" + ++ integer_to_list(C)), + ?line ?t:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]). + +stop_node(Node) -> + ?t:stop_node(Node). + +enable_internal_state() -> + case catch erts_debug:get_internal_state(available_internal_state) of + true -> true; + _ -> erts_debug:set_internal_state(available_internal_state, true) + end. diff --git a/erts/emulator/test/pseudoknot_SUITE.erl b/erts/emulator/test/pseudoknot_SUITE.erl new file mode 100644 index 0000000000..907204cf93 --- /dev/null +++ b/erts/emulator/test/pseudoknot_SUITE.erl @@ -0,0 +1,3326 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(pseudoknot_SUITE). + +-export([all/1,test/1]). + +all(suite) -> [test]. + +test(Config) when is_list(Config) -> + statistics(runtime), + R = loop(1,0), + {_,Time} = statistics(runtime), + io:format("\nruntime = ~p msecs\nresult = ~p\n", [Time,R]), + true = abs(R-33.7976) < 0.0001, + {comment,lists:flatten(io_lib:format("Time: ~w", [Time]))}. + +append([H|T], Z) -> + [H|append(T, Z)]; +append([], X) -> + X. + +atan2(Y,X) when X>0.0 -> + math:atan(Y/X); +atan2(Y,X) when Y<0.0 -> + if + X == 0.0 -> -1.57079632679489661923; + true -> math:atan(Y/X) - 3.14159265358979323846 + end; +atan2(Y,X) -> + if + X == 0.0 -> 1.57079632679489661923; + true -> math:atan(Y/X) + 3.14159265358979323846 + end. + +% -- POINTS ------------------------------------------------------------------ + +%pt ::= {X, Y, Z} where X,Y,Z are floats + +pt_sub({X1, Y1, Z1}, {X2, Y2, Z2}) + when is_float(X1), is_float(Y1), is_float(Z1), + is_float(X2), is_float(Y2), is_float(Z2) -> + {X1 - X2, Y1 - Y2, Z1 - Z2}. + +pt_dist({X1, Y1, Z1}, {X2, Y2, Z2}) + when is_float(X1), is_float(Y1), is_float(Z1), + is_float(X2), is_float(Y2), is_float(Z2) -> + Dx = X1 - X2, + Dy = Y1 - Y2, + Dz = Z1 - Z2, + math:sqrt(Dx * Dx + Dy * Dy + Dz * Dz). + +pt_phi({X, Y, Z}) + when is_float(X), is_float(Z) -> + B = atan2(X, Z), + atan2(math:cos(B) * Z + math:sin(B) * X, Y). + +pt_theta ({X, _, Z}) -> + atan2(X, Z). + +% -- COORDINATE TRANSFORMATIONS ---------------------------------------------- + +% The notation for the transformations follows "Paul, R.P. (1981) Robot +% Manipulators. MIT Press." with the exception that our transformation +% matrices don't have the perspective terms and are the transpose of +% Paul's one. See also "M\"antyl\"a, M. (1985) An Introduction to +% Solid Modeling, Computer Science Press" Appendix A. +% +% The components of a transformation matrix are named like this: +% +% a b c +% d e f +% g h i +% tx ty tz +% +% The components tx, ty, and tz are the translation vector. + +%tfo ::= {A,B,C,D,E,F,G,H,I,Tx,Ty,Tz} where all elements are floats + +tfo_id() -> {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}. + +% The function "tfo-apply" multiplies a transformation matrix, tfo, by a +% point vector, p. The result is a new point. + +tfo_apply ({A,B,C,D,E,F,G,H,I,Tx,Ty,Tz}, {X,Y,Z}) + when is_float(A), is_float(B), is_float(C), is_float(D), is_float(E), + is_float(F), is_float(G), is_float(H), is_float(I), + is_float(Tx), is_float(Ty), is_float(Tz), is_float(X), is_float(Y), is_float(Z) -> + {X * A + Y * D + Z * G + Tx, + X * B + Y * E + Z * H + Ty, + X * C + Y * F + Z * I + Tz}. + +% The function "tfo-combine" multiplies two transformation matrices A and B. +% The result is a new matrix which cumulates the transformations described +% by A and B. + +tfo_combine({A_a,A_b,A_c,A_d,A_e,A_f,A_g,A_h,A_i,A_tx,A_ty,A_tz}, + {B_a,B_b,B_c,B_d,B_e,B_f,B_g,B_h,B_i,B_tx,B_ty,B_tz}) + when is_float(A_a), is_float(A_b), is_float(A_c), is_float(A_d), is_float(A_e), + is_float(A_f), is_float(A_g), is_float(A_h), is_float(A_i), is_float(A_tx), + is_float(A_ty), is_float(A_tz), + is_float(B_a), is_float(B_b), is_float(B_c), is_float(B_d), is_float(B_e), + is_float(B_f), is_float(B_g), is_float(B_h), is_float(B_i), is_float(B_tx), + is_float(B_ty), is_float(B_tz) -> + {A_a * B_a + A_b * B_d + A_c * B_g, + A_a * B_b + A_b * B_e + A_c * B_h, + A_a * B_c + A_b * B_f + A_c * B_i, + A_d * B_a + A_e * B_d + A_f * B_g, + A_d * B_b + A_e * B_e + A_f * B_h, + A_d * B_c + A_e * B_f + A_f * B_i, + A_g * B_a + A_h * B_d + A_i * B_g, + A_g * B_b + A_h * B_e + A_i * B_h, + A_g * B_c + A_h * B_f + A_i * B_i, + A_tx * B_a + A_ty * B_d + A_tz * B_g + B_tx, + A_tx * B_b + A_ty * B_e + A_tz * B_h + B_ty, + A_tx * B_c + A_ty * B_f + A_tz * B_i + B_tz}. + +% The function "tfo-inv-ortho" computes the inverse of a homogeneous +% transformation matrix. + +tfo_inv_ortho({A,B,C,D,E,F,G,H,I,Tx,Ty,Tz}) + when is_float(A), is_float(B), is_float(C), is_float(D), is_float(E), is_float(F), + is_float(G), is_float(H), is_float(I), is_float(Tx), is_float(Ty), is_float(Tz) -> + {A,D,G, + B,E,H, + C,F,I, + -(A * Tx + B * Ty + C * Tz), + -(D * Tx + E * Ty + F * Tz), + -(G * Tx + H * Ty + I * Tz)}. + +% Given three points p1, p2, and p3, the function "tfo-align" computes +% a transformation matrix such that point p1 gets mapped to (0,0,0), p2 gets +% mapped to the Y axis and p3 gets mapped to the YZ plane. + +tfo_align({X1,Y1,Z1},{X2,Y2,Z2},{X3,Y3,Z3}) + when is_float(X1), is_float(Y1), is_float(Z1), + is_float(X2), is_float(Y2), is_float(Z2), + is_float(X3), is_float(Y3), is_float(Z3) -> + X31 = X3 - X1, + Y31 = Y3 - Y1, + Z31 = Z3 - Z1, + Rotpy = pt_sub({X2,Y2,Z2},{X1,Y1,Z1}), + Phi = pt_phi(Rotpy), + Theta = pt_theta(Rotpy), + Sinp = math:sin(Phi), + Sint = math:sin(Theta), + Cosp = math:cos(Phi), + Cost = math:cos(Theta), + Sinpsint = Sinp * Sint, + Sinpcost = Sinp * Cost, + Cospsint = Cosp * Sint, + Cospcost = Cosp * Cost, + Rotpz = {Cost * X31 - Sint * Z31, + Sinpsint * X31 + Cosp * Y31 + Sinpcost * Z31, + Cospsint * X31 - Sinp * Y31 + Cospcost * Z31}, + Rho = pt_theta(Rotpz), + Cosr = math:cos(Rho), + Sinr = math:sin(Rho), + X = Z1 * Sint - X1 * Cost, + Y = -X1 * Sinpsint - Y1 * Cosp - Z1 * Sinpcost, + Z = Y1 * Sinp - Z1 * Cospcost - X1 * Cospsint, + {Cost * Cosr - Cospsint * Sinr, + Sinpsint, + Cost * Sinr + Cospsint * Cosr, + Sinp * Sinr, + Cosp, + -Sinp * Cosr, + -Sint * Cosr - Cospcost * Sinr, + Sinpcost, + Cospcost * Cosr - Sint * Sinr, + X * Cosr - Z * Sinr, + Y, + X * Sinr + Z * Cosr}. + +% -- NUCLEIC ACID CONFORMATIONS DATA BASE ------------------------------------ + +% Numbering of atoms follows the paper: +% +% IUPAC-IUB Joint Commission on Biochemical Nomenclature (JCBN) +% (1983) Abbreviations and Symbols for the Description of +% Conformations of Polynucleotide Chains. Eur. J. Biochem 131, +% 9-15. + +% Define part common to all 4 nucleotide types. + +%nuc ::= { +% tfo,tfo,tfo,tfo, +% pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt, +% pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt, +% A/C/G/U, +% nuc_specific +% } + +% dgf_base_tfo ; defines the standard position for wc and wc_dumas +% p_o3'_275_tfo ; defines the standard position for the connect function +% p_o3'_180_tfo +% p_o3'_60_tfo +% p o1p o2p o5' c5' h5' h5'' c4' h4' o4' c1' h1' c2' h2'' o2' h2' c3' +% h3' o3' n1 n3 c2 c4 c5 c6 + +type({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,X, + _}) -> X. + +nuc_C1_({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,X,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _}) -> X. + +nuc_C2({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,X,_,_,_,_, + _}) -> X. + +nuc_C3_({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + X,_,_,_,_,_,_,_,_,_, + _}) -> X. + +nuc_C4({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,X,_,_,_, + _}) -> X. + +nuc_C4_({_,_,_,_,_,_,_,_,_,_, + _,X,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _}) -> X. + +nuc_N1({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,X,_,_,_,_,_,_, + _}) -> X. + +nuc_O3_({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,X,_,_,_,_,_,_,_, + _}) -> X. + +nuc_P({_,_,_,_,X,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _}) -> X. + +nuc_dgf_base_tfo({X,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _}) -> X. + +nuc_p_o3__180_tfo({_,_,X,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _}) -> X. + +nuc_p_o3__275_tfo({_,X,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _}) -> X. + +nuc_p_o3__60_tfo({_,_,_,X,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _}) -> X. + +rA_N9({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,a, + {_,_,X,_,_,_,_,_}}) -> X. + +rG_N9({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,g, + {_,_,X,_,_,_,_,_,_}}) -> X. + + +%nuc ::= { +% tfo,tfo,tfo,tfo, +% pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt, +% pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt,pt, +% A/C/G/U, +% nuc_specific +% } + +% Define remaining atoms for each nucleotide type. + +%nuc_specific +% a {N6,N7,N9,C8,H2,H61,H62,H8} +% c {N4,O2,H41,H42,H5,H6} +% g {N2,N7,N9,C8,O6,H1,H21,H22,H8} +% u {O2,O4,H3,H5,H6} + +% Database of nucleotide conformations: + +rA() -> + { + {-0.0018, -0.8207, 0.5714, % dgf_base_tfo + 0.2679, -0.5509, -0.7904, + 0.9634, 0.1517, 0.2209, + 0.0073, 8.4030, 0.6232}, + {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo + -0.0433, -0.4257, 0.9038, + -0.5788, 0.7480, 0.3246, + 1.5227, 6.9114, -7.0765}, + {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo + 0.4552, 0.6637, 0.5935, + -0.8042, 0.0203, 0.5941, + -6.9472, -4.1186, -5.9108}, + {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo + -0.8247, 0.5587, -0.0878, + 0.0426, 0.2162, 0.9754, + 6.2694, -7.0540, 3.3316}, + {2.8930, 8.5380, -3.3280}, % P + {1.6980, 7.6960, -3.5570}, % O1P + {3.2260, 9.5010, -4.4020}, % O2P + {4.1590, 7.6040, -3.0340}, % O5' + {5.4550, 8.2120, -2.8810}, % C5' + {5.4546, 8.8508, -1.9978}, % H5' + {5.7588, 8.6625, -3.8259}, % H5'' + {6.4970, 7.1480, -2.5980}, % C4' + {7.4896, 7.5919, -2.5214}, % H4' + {6.1630, 6.4860, -1.3440}, % O4' + {6.5400, 5.1200, -1.4190}, % C1' + {7.2763, 4.9681, -0.6297}, % H1' + {7.1940, 4.8830, -2.7770}, % C2' + {6.8667, 3.9183, -3.1647}, % H2'' + {8.5860, 5.0910, -2.6140}, % O2' + {8.9510, 4.7626, -1.7890}, % H2' + {6.5720, 6.0040, -3.6090}, % C3' + {5.5636, 5.7066, -3.8966}, % H3' + {7.3801, 6.3562, -4.7350}, % O3' + {4.7150, 0.4910, -0.1360}, % N1 + {6.3490, 2.1730, -0.6020}, % N3 + {5.9530, 0.9650, -0.2670}, % C2 + {5.2900, 2.9790, -0.8260}, % C4 + {3.9720, 2.6390, -0.7330}, % C5 + {3.6770, 1.3160, -0.3660}, % C6 + a, { + {2.4280, 0.8450, -0.2360}, % N6 + {3.1660, 3.7290, -1.0360}, % N7 + {5.3170, 4.2990, -1.1930}, % N9 + {4.0100, 4.6780, -1.2990}, % C8 + {6.6890, 0.1903, -0.0518}, % H2 + {1.6470, 1.4460, -0.4040}, % H61 + {2.2780, -0.1080, -0.0280}, % H62 + {3.4421, 5.5744, -1.5482}} % H8 + }. + +rA01() -> + { + {-0.0043, -0.8175, 0.5759, % dgf_base_tfo + 0.2617, -0.5567, -0.7884, + 0.9651, 0.1473, 0.2164, + 0.0359, 8.3929, 0.5532}, + {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo + -0.0433, -0.4257, 0.9038, + -0.5788, 0.7480, 0.3246, + 1.5227, 6.9114, -7.0765}, + {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo + 0.4552, 0.6637, 0.5935, + -0.8042, 0.0203, 0.5941, + -6.9472, -4.1186, -5.9108}, + {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo + -0.8247, 0.5587, -0.0878, + 0.0426, 0.2162, 0.9754, + 6.2694, -7.0540, 3.3316}, + {2.8930, 8.5380, -3.3280}, % P + {1.6980, 7.6960, -3.5570}, % O1P + {3.2260, 9.5010, -4.4020}, % O2P + {4.1590, 7.6040, -3.0340}, % O5' + {5.4352, 8.2183, -2.7757}, % C5' + {5.3830, 8.7883, -1.8481}, % H5' + {5.7729, 8.7436, -3.6691}, % H5'' + {6.4830, 7.1518, -2.5252}, % C4' + {7.4749, 7.5972, -2.4482}, % H4' + {6.1626, 6.4620, -1.2827}, % O4' + {6.5431, 5.0992, -1.3905}, % C1' + {7.2871, 4.9328, -0.6114}, % H1' + {7.1852, 4.8935, -2.7592}, % C2' + {6.8573, 3.9363, -3.1645}, % H2'' + {8.5780, 5.1025, -2.6046}, % O2' + {8.9516, 4.7577, -1.7902}, % H2' + {6.5522, 6.0300, -3.5612}, % C3' + {5.5420, 5.7356, -3.8459}, % H3' + {7.3487, 6.4089, -4.6867}, % O3' + {4.7442, 0.4514, -0.1390}, % N1 + {6.3687, 2.1459, -0.5926}, % N3 + {5.9795, 0.9335, -0.2657}, % C2 + {5.3052, 2.9471, -0.8125}, % C4 + {3.9891, 2.5987, -0.7230}, % C5 + {3.7016, 1.2717, -0.3647}, % C6 + a, { + {2.4553, 0.7925, -0.2390}, % N6 + {3.1770, 3.6859, -1.0198}, % N7 + {5.3247, 4.2695, -1.1710}, % N9 + {4.0156, 4.6415, -1.2759}, % C8 + {6.7198, 0.1618, -0.0547}, % H2 + {1.6709, 1.3900, -0.4039}, % H61 + {2.3107, -0.1627, -0.0373}, % H62 + {3.4426, 5.5361, -1.5199}} % H8 + }. + +rA02() -> + { + {0.5566, 0.0449, 0.8296, % dgf_base_tfo + 0.5125, 0.7673, -0.3854, + -0.6538, 0.6397, 0.4041, + -9.1161, -3.7679, -2.9968}, + {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo + -0.0433, -0.4257, 0.9038, + -0.5788, 0.7480, 0.3246, + 1.5227, 6.9114, -7.0765}, + {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo + 0.4552, 0.6637, 0.5935, + -0.8042, 0.0203, 0.5941, + -6.9472, -4.1186, -5.9108}, + {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo + -0.8247, 0.5587, -0.0878, + 0.0426, 0.2162, 0.9754, + 6.2694, -7.0540, 3.3316}, + {2.8930, 8.5380, -3.3280}, % P + {1.6980, 7.6960, -3.5570}, % O1P + {3.2260, 9.5010, -4.4020}, % O2P + {4.1590, 7.6040, -3.0340}, % O5' + {4.5778, 6.6594, -4.0364}, % C5' + {4.9220, 7.1963, -4.9204}, % H5' + {3.7996, 5.9091, -4.1764}, % H5'' + {5.7873, 5.8869, -3.5482}, % C4' + {6.0405, 5.0875, -4.2446}, % H4' + {6.9135, 6.8036, -3.4310}, % O4' + {7.7293, 6.4084, -2.3392}, % C1' + {8.7078, 6.1815, -2.7624}, % H1' + {7.1305, 5.1418, -1.7347}, % C2' + {7.2040, 5.1982, -0.6486}, % H2'' + {7.7417, 4.0392, -2.3813}, % O2' + {8.6785, 4.1443, -2.5630}, % H2' + {5.6666, 5.2728, -2.1536}, % C3' + {5.1747, 5.9805, -1.4863}, % H3' + {4.9997, 4.0086, -2.1973}, % O3' + {10.3245, 8.5459, 1.5467}, % N1 + {9.8051, 6.9432, -0.1497}, % N3 + {10.5175, 7.4328, 0.8408}, % C2 + {8.7523, 7.7422, -0.4228}, % C4 + {8.4257, 8.9060, 0.2099}, % C5 + {9.2665, 9.3242, 1.2540}, % C6 + a, { + {9.0664, 10.4462, 1.9610}, % N6 + {7.2750, 9.4537, -0.3428}, % N7 + {7.7962, 7.5519, -1.3859}, % N9 + {6.9479, 8.6157, -1.2771}, % C8 + {11.4063, 6.9047, 1.1859}, % H2 + {8.2845, 11.0341, 1.7552}, % H61 + {9.6584, 10.6647, 2.7198}, % H62 + {6.0430, 8.9853, -1.7594}} % H8 + }. + +rA03() -> + { + {-0.5021, 0.0731, 0.8617, % dgf_base_tfo + -0.8112, 0.3054, -0.4986, + -0.2996, -0.9494, -0.0940, + 6.4273, -5.1944, -3.7807}, + {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo + -0.0433, -0.4257, 0.9038, + -0.5788, 0.7480, 0.3246, + 1.5227, 6.9114, -7.0765}, + {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo + 0.4552, 0.6637, 0.5935, + -0.8042, 0.0203, 0.5941, + -6.9472, -4.1186, -5.9108}, + {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo + -0.8247, 0.5587, -0.0878, + 0.0426, 0.2162, 0.9754, + 6.2694, -7.0540, 3.3316}, + {2.8930, 8.5380, -3.3280}, % P + {1.6980, 7.6960, -3.5570}, % O1P + {3.2260, 9.5010, -4.4020}, % O2P + {4.1590, 7.6040, -3.0340}, % O5' + {4.1214, 6.7116, -1.9049}, % C5' + {3.3465, 5.9610, -2.0607}, % H5' + {4.0789, 7.2928, -0.9837}, % H5'' + {5.4170, 5.9293, -1.8186}, % C4' + {5.4506, 5.3400, -0.9023}, % H4' + {5.5067, 5.0417, -2.9703}, % O4' + {6.8650, 4.9152, -3.3612}, % C1' + {7.1090, 3.8577, -3.2603}, % H1' + {7.7152, 5.7282, -2.3894}, % C2' + {8.5029, 6.2356, -2.9463}, % H2'' + {8.1036, 4.8568, -1.3419}, % O2' + {8.3270, 3.9651, -1.6184}, % H2' + {6.7003, 6.7565, -1.8911}, % C3' + {6.5898, 7.5329, -2.6482}, % H3' + {7.0505, 7.2878, -0.6105}, % O3' + {9.6740, 4.7656, -7.6614}, % N1 + {9.0739, 4.3013, -5.3941}, % N3 + {9.8416, 4.2192, -6.4581}, % C2 + {7.9885, 5.0632, -5.6446}, % C4 + {7.6822, 5.6856, -6.8194}, % C5 + {8.5831, 5.5215, -7.8840}, % C6 + a, { + {8.4084, 6.0747, -9.0933}, % N6 + {6.4857, 6.3816, -6.7035}, % N7 + {6.9740, 5.3703, -4.7760}, % N9 + {6.1133, 6.1613, -5.4808}, % C8 + {10.7627, 3.6375, -6.4220}, % H2 + {7.6031, 6.6390, -9.2733}, % H61 + {9.1004, 5.9708, -9.7893}, % H62 + {5.1705, 6.6830, -5.3167}} % H8 + }. + +rA04() -> + { + {-0.5426, -0.8175, 0.1929, % dgf_base_tfo + 0.8304, -0.5567, -0.0237, + 0.1267, 0.1473, 0.9809, + -0.5075, 8.3929, 0.2229}, + {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo + -0.0433, -0.4257, 0.9038, + -0.5788, 0.7480, 0.3246, + 1.5227, 6.9114, -7.0765}, + {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo + 0.4552, 0.6637, 0.5935, + -0.8042, 0.0203, 0.5941, + -6.9472, -4.1186, -5.9108}, + {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo + -0.8247, 0.5587, -0.0878, + 0.0426, 0.2162, 0.9754, + 6.2694, -7.0540, 3.3316}, + {2.8930, 8.5380, -3.3280}, % P + {1.6980, 7.6960, -3.5570}, % O1P + {3.2260, 9.5010, -4.4020}, % O2P + {4.1590, 7.6040, -3.0340}, % O5' + {5.4352, 8.2183, -2.7757}, % C5' + {5.3830, 8.7883, -1.8481}, % H5' + {5.7729, 8.7436, -3.6691}, % H5'' + {6.4830, 7.1518, -2.5252}, % C4' + {7.4749, 7.5972, -2.4482}, % H4' + {6.1626, 6.4620, -1.2827}, % O4' + {6.5431, 5.0992, -1.3905}, % C1' + {7.2871, 4.9328, -0.6114}, % H1' + {7.1852, 4.8935, -2.7592}, % C2' + {6.8573, 3.9363, -3.1645}, % H2'' + {8.5780, 5.1025, -2.6046}, % O2' + {8.9516, 4.7577, -1.7902}, % H2' + {6.5522, 6.0300, -3.5612}, % C3' + {5.5420, 5.7356, -3.8459}, % H3' + {7.3487, 6.4089, -4.6867}, % O3' + {3.6343, 2.6680, 2.0783}, % N1 + {5.4505, 3.9805, 1.2446}, % N3 + {4.7540, 3.3816, 2.1851}, % C2 + {4.8805, 3.7951, 0.0354}, % C4 + {3.7416, 3.0925, -0.2305}, % C5 + {3.0873, 2.4980, 0.8606}, % C6 + a, { + {1.9600, 1.7805, 0.7462}, % N6 + {3.4605, 3.1184, -1.5906}, % N7 + {5.3247, 4.2695, -1.1710}, % N9 + {4.4244, 3.8244, -2.0953}, % C8 + {5.0814, 3.4352, 3.2234}, % H2 + {1.5423, 1.6454, -0.1520}, % H61 + {1.5716, 1.3398, 1.5392}, % H62 + {4.2675, 3.8876, -3.1721}} % H8 + }. + +rA05() -> + { + {-0.5891, 0.0449, 0.8068, % dgf_base_tfo + 0.5375, 0.7673, 0.3498, + -0.6034, 0.6397, -0.4762, + -0.3019, -3.7679, -9.5913}, + {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo + -0.0433, -0.4257, 0.9038, + -0.5788, 0.7480, 0.3246, + 1.5227, 6.9114, -7.0765}, + {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo + 0.4552, 0.6637, 0.5935, + -0.8042, 0.0203, 0.5941, + -6.9472, -4.1186, -5.9108}, + {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo + -0.8247, 0.5587, -0.0878, + 0.0426, 0.2162, 0.9754, + 6.2694, -7.0540, 3.3316}, + {2.8930, 8.5380, -3.3280}, % P + {1.6980, 7.6960, -3.5570}, % O1P + {3.2260, 9.5010, -4.4020}, % O2P + {4.1590, 7.6040, -3.0340}, % O5' + {4.5778, 6.6594, -4.0364}, % C5' + {4.9220, 7.1963, -4.9204}, % H5' + {3.7996, 5.9091, -4.1764}, % H5'' + {5.7873, 5.8869, -3.5482}, % C4' + {6.0405, 5.0875, -4.2446}, % H4' + {6.9135, 6.8036, -3.4310}, % O4' + {7.7293, 6.4084, -2.3392}, % C1' + {8.7078, 6.1815, -2.7624}, % H1' + {7.1305, 5.1418, -1.7347}, % C2' + {7.2040, 5.1982, -0.6486}, % H2'' + {7.7417, 4.0392, -2.3813}, % O2' + {8.6785, 4.1443, -2.5630}, % H2' + {5.6666, 5.2728, -2.1536}, % C3' + {5.1747, 5.9805, -1.4863}, % H3' + {4.9997, 4.0086, -2.1973}, % O3' + {10.2594, 10.6774, -1.0056}, % N1 + {9.7528, 8.7080, -2.2631}, % N3 + {10.4471, 9.7876, -1.9791}, % C2 + {8.7271, 8.5575, -1.3991}, % C4 + {8.4100, 9.3803, -0.3580}, % C5 + {9.2294, 10.5030, -0.1574}, % C6 + a, { + {9.0349, 11.3951, 0.8250}, % N6 + {7.2891, 8.9068, 0.3121}, % N7 + {7.7962, 7.5519, -1.3859}, % N9 + {6.9702, 7.8292, -0.3353}, % C8 + {11.3132, 10.0537, -2.5851}, % H2 + {8.2741, 11.2784, 1.4629}, % H61 + {9.6733, 12.1368, 0.9529}, % H62 + {6.0888, 7.3990, 0.1403}} % H8 + }. + +rA06() -> + { + {-0.9815, 0.0731, -0.1772, % dgf_base_tfo + 0.1912, 0.3054, -0.9328, + -0.0141, -0.9494, -0.3137, + 5.7506, -5.1944, 4.7470}, + {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo + -0.0433, -0.4257, 0.9038, + -0.5788, 0.7480, 0.3246, + 1.5227, 6.9114, -7.0765}, + {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo + 0.4552, 0.6637, 0.5935, + -0.8042, 0.0203, 0.5941, + -6.9472, -4.1186, -5.9108}, + {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo + -0.8247, 0.5587, -0.0878, + 0.0426, 0.2162, 0.9754, + 6.2694, -7.0540, 3.3316}, + {2.8930, 8.5380, -3.3280}, % P + {1.6980, 7.6960, -3.5570}, % O1P + {3.2260, 9.5010, -4.4020}, % O2P + {4.1590, 7.6040, -3.0340}, % O5' + {4.1214, 6.7116, -1.9049}, % C5' + {3.3465, 5.9610, -2.0607}, % H5' + {4.0789, 7.2928, -0.9837}, % H5'' + {5.4170, 5.9293, -1.8186}, % C4' + {5.4506, 5.3400, -0.9023}, % H4' + {5.5067, 5.0417, -2.9703}, % O4' + {6.8650, 4.9152, -3.3612}, % C1' + {7.1090, 3.8577, -3.2603}, % H1' + {7.7152, 5.7282, -2.3894}, % C2' + {8.5029, 6.2356, -2.9463}, % H2'' + {8.1036, 4.8568, -1.3419}, % O2' + {8.3270, 3.9651, -1.6184}, % H2' + {6.7003, 6.7565, -1.8911}, % C3' + {6.5898, 7.5329, -2.6482}, % H3' + {7.0505, 7.2878, -0.6105}, % O3' + {6.6624, 3.5061, -8.2986}, % N1 + {6.5810, 3.2570, -5.9221}, % N3 + {6.5151, 2.8263, -7.1625}, % C2 + {6.8364, 4.5817, -5.8882}, % C4 + {7.0116, 5.4064, -6.9609}, % C5 + {6.9173, 4.8260, -8.2361}, % C6 + a, { + {7.0668, 5.5163, -9.3763}, % N6 + {7.2573, 6.7070, -6.5394}, % N7 + {6.9740, 5.3703, -4.7760}, % N9 + {7.2238, 6.6275, -5.2453}, % C8 + {6.3146, 1.7741, -7.3641}, % H2 + {7.2568, 6.4972, -9.3456}, % H61 + {7.0437, 5.0478, -10.2446}, % H62 + {7.4108, 7.6227, -4.8418}} % H8 + }. + +rA07() -> + { + {0.2379, 0.1310, -0.9624, % dgf_base_tfo + -0.5876, -0.7696, -0.2499, + -0.7734, 0.6249, -0.1061, + 30.9870, -26.9344, 42.6416}, + {0.7529, 0.1548, 0.6397, % p_o3'_275_tfo + 0.2952, -0.9481, -0.1180, + 0.5882, 0.2777, -0.7595, + -58.8919, -11.3095, 6.0866}, + {-0.0239, 0.9667, -0.2546, % p_o3'_180_tfo + 0.9731, -0.0359, -0.2275, + -0.2290, -0.2532, -0.9399, + 3.5401, -29.7913, 52.2796}, + {-0.8912, -0.4531, 0.0242, % p_o3'_60_tfo + -0.1183, 0.1805, -0.9764, + 0.4380, -0.8730, -0.2145, + 19.9023, 54.8054, 15.2799}, + {41.8210, 8.3880, 43.5890}, % P + {42.5400, 8.0450, 44.8330}, % O1P + {42.2470, 9.6920, 42.9910}, % O2P + {40.2550, 8.2030, 43.7340}, % O5' + {39.3505, 8.4697, 42.6565}, % C5' + {39.1377, 7.5433, 42.1230}, % H5' + {39.7203, 9.3119, 42.0717}, % H5'' + {38.0405, 8.9195, 43.2869}, % C4' + {37.3687, 9.3036, 42.5193}, % H4' + {37.4319, 7.8146, 43.9387}, % O4' + {37.1959, 8.1354, 45.3237}, % C1' + {36.1788, 8.5202, 45.3970}, % H1' + {38.1721, 9.2328, 45.6504}, % C2' + {39.1555, 8.7939, 45.8188}, % H2'' + {37.7862, 10.0617, 46.7013}, % O2' + {37.3087, 9.6229, 47.4092}, % H2' + {38.1844, 10.0268, 44.3367}, % C3' + {39.1578, 10.5054, 44.2289}, % H3' + {37.0547, 10.9127, 44.3441}, % O3' + {34.8811, 4.2072, 47.5784}, % N1 + {35.1084, 6.1336, 46.1818}, % N3 + {34.4108, 5.1360, 46.7207}, % C2 + {36.3908, 6.1224, 46.6053}, % C4 + {36.9819, 5.2334, 47.4697}, % C5 + {36.1786, 4.1985, 48.0035}, % C6 + a, { + {36.6103, 3.2749, 48.8452}, % N6 + {38.3236, 5.5522, 47.6595}, % N7 + {37.3887, 7.0024, 46.2437}, % N9 + {38.5055, 6.6096, 46.9057}, % C8 + {33.3553, 5.0152, 46.4771}, % H2 + {37.5730, 3.2804, 49.1507}, % H61 + {35.9775, 2.5638, 49.1828}, % H62 + {39.5461, 6.9184, 47.0041}} % H8 + }. + +rA08() -> + { + {0.1084, -0.0895, -0.9901, % dgf_base_tfo + 0.9789, -0.1638, 0.1220, + -0.1731, -0.9824, 0.0698, + -2.9039, 47.2655, 33.0094}, + {0.7529, 0.1548, 0.6397, % p_o3'_275_tfo + 0.2952, -0.9481, -0.1180, + 0.5882, 0.2777, -0.7595, + -58.8919, -11.3095, 6.0866}, + {-0.0239, 0.9667, -0.2546, % p_o3'_180_tfo + 0.9731, -0.0359, -0.2275, + -0.2290, -0.2532, -0.9399, + 3.5401, -29.7913, 52.2796}, + {-0.8912, -0.4531, 0.0242, % p_o3'_60_tfo + -0.1183, 0.1805, -0.9764, + 0.4380, -0.8730, -0.2145, + 19.9023, 54.8054, 15.2799}, + {41.8210, 8.3880, 43.5890}, % P + {42.5400, 8.0450, 44.8330}, % O1P + {42.2470, 9.6920, 42.9910}, % O2P + {40.2550, 8.2030, 43.7340}, % O5' + {39.4850, 8.9301, 44.6977}, % C5' + {39.0638, 9.8199, 44.2296}, % H5' + {40.0757, 9.0713, 45.6029}, % H5'' + {38.3102, 8.0414, 45.0789}, % C4' + {37.7842, 8.4637, 45.9351}, % H4' + {37.4200, 7.9453, 43.9769}, % O4' + {37.2249, 6.5609, 43.6273}, % C1' + {36.3360, 6.2168, 44.1561}, % H1' + {38.4347, 5.8414, 44.1590}, % C2' + {39.2688, 5.9974, 43.4749}, % H2'' + {38.2344, 4.4907, 44.4348}, % O2' + {37.6374, 4.0386, 43.8341}, % H2' + {38.6926, 6.6079, 45.4637}, % C3' + {39.7585, 6.5640, 45.6877}, % H3' + {37.8238, 6.0705, 46.4723}, % O3' + {33.9162, 6.2598, 39.7758}, % N1 + {34.6709, 6.5759, 42.0215}, % N3 + {33.7257, 6.5186, 41.0858}, % C2 + {35.8935, 6.3324, 41.5018}, % C4 + {36.2105, 6.0601, 40.1932}, % C5 + {35.1538, 6.0151, 39.2537}, % C6 + a, { + {35.3088, 5.7642, 37.9649}, % N6 + {37.5818, 5.8677, 40.0507}, % N7 + {37.0932, 6.3197, 42.1810}, % N9 + {38.0509, 6.0354, 41.2635}, % C8 + {32.6830, 6.6898, 41.3532}, % H2 + {36.2305, 5.5855, 37.5925}, % H61 + {34.5056, 5.7512, 37.3528}, % H62 + {39.1318, 5.8993, 41.2285}} % H8 + }. + +rA09() -> + { + {0.8467, 0.4166, -0.3311, % dgf_base_tfo + -0.3962, 0.9089, 0.1303, + 0.3552, 0.0209, 0.9346, + -42.7319, -26.6223, -29.8163}, + {0.7529, 0.1548, 0.6397, % p_o3'_275_tfo + 0.2952, -0.9481, -0.1180, + 0.5882, 0.2777, -0.7595, + -58.8919, -11.3095, 6.0866}, + {-0.0239, 0.9667, -0.2546, % p_o3'_180_tfo + 0.9731, -0.0359, -0.2275, + -0.2290, -0.2532, -0.9399, + 3.5401, -29.7913, 52.2796}, + {-0.8912, -0.4531, 0.0242, % p_o3'_60_tfo + -0.1183, 0.1805, -0.9764, + 0.4380, -0.8730, -0.2145, + 19.9023, 54.8054, 15.2799}, + {41.8210, 8.3880, 43.5890}, % P + {42.5400, 8.0450, 44.8330}, % O1P + {42.2470, 9.6920, 42.9910}, % O2P + {40.2550, 8.2030, 43.7340}, % O5' + {39.3505, 8.4697, 42.6565}, % C5' + {39.1377, 7.5433, 42.1230}, % H5' + {39.7203, 9.3119, 42.0717}, % H5'' + {38.0405, 8.9195, 43.2869}, % C4' + {37.6479, 8.1347, 43.9335}, % H4' + {38.2691, 10.0933, 44.0524}, % O4' + {37.3999, 11.1488, 43.5973}, % C1' + {36.5061, 11.1221, 44.2206}, % H1' + {37.0364, 10.7838, 42.1836}, % C2' + {37.8636, 11.0489, 41.5252}, % H2'' + {35.8275, 11.3133, 41.7379}, % O2' + {35.6214, 12.1896, 42.0714}, % H2' + {36.9316, 9.2556, 42.2837}, % C3' + {37.1778, 8.8260, 41.3127}, % H3' + {35.6285, 8.9334, 42.7926}, % O3' + {38.1482, 15.2833, 46.4641}, % N1 + {37.3641, 13.0968, 45.9007}, % N3 + {37.5032, 14.1288, 46.7300}, % C2 + {37.9570, 13.3377, 44.7113}, % C4 + {38.6397, 14.4660, 44.3267}, % C5 + {38.7473, 15.5229, 45.2609}, % C6 + a, { + {39.3720, 16.6649, 45.0297}, % N6 + {39.1079, 14.3351, 43.0223}, % N7 + {38.0132, 12.4868, 43.6280}, % N9 + {38.7058, 13.1402, 42.6620}, % C8 + {37.0731, 14.0857, 47.7306}, % H2 + {39.8113, 16.8281, 44.1350}, % H61 + {39.4100, 17.3741, 45.7478}, % H62 + {39.0412, 12.9660, 41.6397}} % H8 + }. + +rA10() -> + { + {0.7063, 0.6317, -0.3196, % dgf_base_tfo + -0.0403, -0.4149, -0.9090, + -0.7068, 0.6549, -0.2676, + 6.4402, -52.1496, 30.8246}, + {0.7529, 0.1548, 0.6397, % p_o3'_275_tfo + 0.2952, -0.9481, -0.1180, + 0.5882, 0.2777, -0.7595, + -58.8919, -11.3095, 6.0866}, + {-0.0239, 0.9667, -0.2546, % p_o3'_180_tfo + 0.9731, -0.0359, -0.2275, + -0.2290, -0.2532, -0.9399, + 3.5401, -29.7913, 52.2796}, + {-0.8912, -0.4531, 0.0242, % p_o3'_60_tfo + -0.1183, 0.1805, -0.9764, + 0.4380, -0.8730, -0.2145, + 19.9023, 54.8054, 15.2799}, + {41.8210, 8.3880, 43.5890}, % P + {42.5400, 8.0450, 44.8330}, % O1P + {42.2470, 9.6920, 42.9910}, % O2P + {40.2550, 8.2030, 43.7340}, % O5' + {39.4850, 8.9301, 44.6977}, % C5' + {39.0638, 9.8199, 44.2296}, % H5' + {40.0757, 9.0713, 45.6029}, % H5'' + {38.3102, 8.0414, 45.0789}, % C4' + {37.7099, 7.8166, 44.1973}, % H4' + {38.8012, 6.8321, 45.6380}, % O4' + {38.2431, 6.6413, 46.9529}, % C1' + {37.3505, 6.0262, 46.8385}, % H1' + {37.8484, 8.0156, 47.4214}, % C2' + {38.7381, 8.5406, 47.7690}, % H2'' + {36.8286, 8.0368, 48.3701}, % O2' + {36.8392, 7.3063, 48.9929}, % H2' + {37.3576, 8.6512, 46.1132}, % C3' + {37.5207, 9.7275, 46.1671}, % H3' + {35.9985, 8.2392, 45.9032}, % O3' + {39.9117, 2.2278, 48.8527}, % N1 + {38.6207, 3.6941, 47.4757}, % N3 + {38.9872, 2.4888, 47.9057}, % C2 + {39.2961, 4.6720, 48.1174}, % C4 + {40.2546, 4.5307, 49.0912}, % C5 + {40.5932, 3.2189, 49.4985}, % C6 + a, { + {41.4938, 2.9317, 50.4229}, % N6 + {40.7195, 5.7755, 49.5060}, % N7 + {39.1730, 6.0305, 47.9170}, % N9 + {40.0413, 6.6250, 48.7728}, % C8 + {38.5257, 1.5960, 47.4838}, % H2 + {41.9907, 3.6753, 50.8921}, % H61 + {41.6848, 1.9687, 50.6599}, % H62 + {40.3571, 7.6321, 49.0452}} % H8 + }. + +rAs() -> [rA01(),rA02(),rA03(),rA04(),rA05(),rA06(),rA07(), + rA08(),rA09(),rA10()]. + +rC() -> + { + {-0.0359, -0.8071, 0.5894, % dgf_base_tfo + -0.2669, 0.5761, 0.7726, + -0.9631, -0.1296, -0.2361, + 0.1584, 8.3434, 0.5434}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {5.2430, -8.2420, 2.8260}, % C5' + {5.1974, -8.8497, 1.9223}, % H5' + {5.5548, -8.7348, 3.7469}, % H5'' + {6.3140, -7.2060, 2.5510}, % C4' + {7.2954, -7.6762, 2.4898}, % H4' + {6.0140, -6.5420, 1.2890}, % O4' + {6.4190, -5.1840, 1.3620}, % C1' + {7.1608, -5.0495, 0.5747}, % H1' + {7.0760, -4.9560, 2.7270}, % C2' + {6.7770, -3.9803, 3.1099}, % H2'' + {8.4500, -5.1930, 2.5810}, % O2' + {8.8309, -4.8755, 1.7590}, % H2' + {6.4060, -6.0590, 3.5580}, % C3' + {5.4021, -5.7313, 3.8281}, % H3' + {7.1570, -6.4240, 4.7070}, % O3' + {5.2170, -4.3260, 1.1690}, % N1 + {4.2960, -2.2560, 0.6290}, % N3 + {5.4330, -3.0200, 0.7990}, % C2 + {2.9930, -2.6780, 0.7940}, % C4 + {2.8670, -4.0630, 1.1830}, % C5 + {3.9570, -4.8300, 1.3550}, % C6 + c, { + {2.0187, -1.8047, 0.5874}, % N4 + {6.5470, -2.5560, 0.6290}, % O2 + {1.0684, -2.1236, 0.7109}, % H41 + {2.2344, -0.8560, 0.3162}, % H42 + {1.8797, -4.4972, 1.3404}, % H5 + {3.8479, -5.8742, 1.6480}} % H6 + }. + +rC01() -> + { + {-0.0137, -0.8012, 0.5983, % dgf_base_tfo + -0.2523, 0.5817, 0.7733, + -0.9675, -0.1404, -0.2101, + 0.2031, 8.3874, 0.4228}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {5.2416, -8.2422, 2.8181}, % C5' + {5.2050, -8.8128, 1.8901}, % H5' + {5.5368, -8.7738, 3.7227}, % H5'' + {6.3232, -7.2037, 2.6002}, % C4' + {7.3048, -7.6757, 2.5577}, % H4' + {6.0635, -6.5092, 1.3456}, % O4' + {6.4697, -5.1547, 1.4629}, % C1' + {7.2354, -5.0043, 0.7018}, % H1' + {7.0856, -4.9610, 2.8521}, % C2' + {6.7777, -3.9935, 3.2487}, % H2'' + {8.4627, -5.1992, 2.7423}, % O2' + {8.8693, -4.8638, 1.9399}, % H2' + {6.3877, -6.0809, 3.6362}, % C3' + {5.3770, -5.7562, 3.8834}, % H3' + {7.1024, -6.4754, 4.7985}, % O3' + {5.2764, -4.2883, 1.2538}, % N1 + {4.3777, -2.2062, 0.7229}, % N3 + {5.5069, -2.9779, 0.9088}, % C2 + {3.0693, -2.6246, 0.8500}, % C4 + {2.9279, -4.0146, 1.2149}, % C5 + {4.0101, -4.7892, 1.4017}, % C6 + c, { + {2.1040, -1.7437, 0.6331}, % N4 + {6.6267, -2.5166, 0.7728}, % O2 + {1.1496, -2.0600, 0.7287}, % H41 + {2.3303, -0.7921, 0.3815}, % H42 + {1.9353, -4.4465, 1.3419}, % H5 + {3.8895, -5.8371, 1.6762}} % H6 + }. + +rC02() -> + { + {0.5141, 0.0246, 0.8574, % dgf_base_tfo + -0.5547, -0.7529, 0.3542, + 0.6542, -0.6577, -0.3734, + -9.1111, -3.4598, -3.2939}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {4.3825, -6.6585, 4.0489}, % C5' + {4.6841, -7.2019, 4.9443}, % H5' + {3.6189, -5.8889, 4.1625}, % H5'' + {5.6255, -5.9175, 3.5998}, % C4' + {5.8732, -5.1228, 4.3034}, % H4' + {6.7337, -6.8605, 3.5222}, % O4' + {7.5932, -6.4923, 2.4548}, % C1' + {8.5661, -6.2983, 2.9064}, % H1' + {7.0527, -5.2012, 1.8322}, % C2' + {7.1627, -5.2525, 0.7490}, % H2'' + {7.6666, -4.1249, 2.4880}, % O2' + {8.5944, -4.2543, 2.6981}, % H2' + {5.5661, -5.3029, 2.2009}, % C3' + {5.0841, -6.0018, 1.5172}, % H3' + {4.9062, -4.0452, 2.2042}, % O3' + {7.6298, -7.6136, 1.4752}, % N1 + {8.6945, -8.7046, -0.2857}, % N3 + {8.6943, -7.6514, 0.6066}, % C2 + {7.7426, -9.6987, -0.3801}, % C4 + {6.6642, -9.5742, 0.5722}, % C5 + {6.6391, -8.5592, 1.4526}, % C6 + c, { + {7.9033, -10.6371, -1.3010}, % N4 + {9.5840, -6.8186, 0.6136}, % O2 + {7.2009, -11.3604, -1.3619}, % H41 + {8.7058, -10.6168, -1.9140}, % H42 + {5.8585, -10.3083, 0.5822}, % H5 + {5.8197, -8.4773, 2.1667}} % H6 + }. + +rC03() -> + { + {-0.4993, 0.0476, 0.8651, % dgf_base_tfo + 0.8078, -0.3353, 0.4847, + 0.3132, 0.9409, 0.1290, + 6.2989, -5.2303, -3.8577}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {3.9938, -6.7042, 1.9023}, % C5' + {3.2332, -5.9343, 2.0319}, % H5' + {3.9666, -7.2863, 0.9812}, % H5'' + {5.3098, -5.9546, 1.8564}, % C4' + {5.3863, -5.3702, 0.9395}, % H4' + {5.3851, -5.0642, 3.0076}, % O4' + {6.7315, -4.9724, 3.4462}, % C1' + {7.0033, -3.9202, 3.3619}, % H1' + {7.5997, -5.8018, 2.4948}, % C2' + {8.3627, -6.3254, 3.0707}, % H2'' + {8.0410, -4.9501, 1.4724}, % O2' + {8.2781, -4.0644, 1.7570}, % H2' + {6.5701, -6.8129, 1.9714}, % C3' + {6.4186, -7.5809, 2.7299}, % H3' + {6.9357, -7.3841, 0.7235}, % O3' + {6.8024, -5.4718, 4.8475}, % N1 + {7.9218, -5.5700, 6.8877}, % N3 + {7.8908, -5.0886, 5.5944}, % C2 + {6.9789, -6.3827, 7.4823}, % C4 + {5.8742, -6.7319, 6.6202}, % C5 + {5.8182, -6.2769, 5.3570}, % C6 + c, { + {7.1702, -6.7511, 8.7402}, % N4 + {8.7747, -4.3728, 5.1568}, % O2 + {6.4741, -7.3461, 9.1662}, % H41 + {7.9889, -6.4396, 9.2429}, % H42 + {5.0736, -7.3713, 6.9922}, % H5 + {4.9784, -6.5473, 4.7170}} % H6 + }. + +rC04() -> + { + {-0.5669, -0.8012, 0.1918, % dgf_base_tfo + -0.8129, 0.5817, 0.0273, + -0.1334, -0.1404, -0.9811, + -0.3279, 8.3874, 0.3355}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {5.2416, -8.2422, 2.8181}, % C5' + {5.2050, -8.8128, 1.8901}, % H5' + {5.5368, -8.7738, 3.7227}, % H5'' + {6.3232, -7.2037, 2.6002}, % C4' + {7.3048, -7.6757, 2.5577}, % H4' + {6.0635, -6.5092, 1.3456}, % O4' + {6.4697, -5.1547, 1.4629}, % C1' + {7.2354, -5.0043, 0.7018}, % H1' + {7.0856, -4.9610, 2.8521}, % C2' + {6.7777, -3.9935, 3.2487}, % H2'' + {8.4627, -5.1992, 2.7423}, % O2' + {8.8693, -4.8638, 1.9399}, % H2' + {6.3877, -6.0809, 3.6362}, % C3' + {5.3770, -5.7562, 3.8834}, % H3' + {7.1024, -6.4754, 4.7985}, % O3' + {5.2764, -4.2883, 1.2538}, % N1 + {3.8961, -3.0896, -0.1893}, % N3 + {5.0095, -3.8907, -0.0346}, % C2 + {3.0480, -2.6632, 0.8116}, % C4 + {3.4093, -3.1310, 2.1292}, % C5 + {4.4878, -3.9124, 2.3088}, % C6 + c, { + {2.0216, -1.8941, 0.4804}, % N4 + {5.7005, -4.2164, -0.9842}, % O2 + {1.4067, -1.5873, 1.2205}, % H41 + {1.8721, -1.6319, -0.4835}, % H42 + {2.8048, -2.8507, 2.9918}, % H5 + {4.7491, -4.2593, 3.3085}} % H6 + }. + +rC05() -> + { + {-0.6298, 0.0246, 0.7763, % dgf_base_tfo + -0.5226, -0.7529, -0.4001, + 0.5746, -0.6577, 0.4870, + -0.0208, -3.4598, -9.6882}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {4.3825, -6.6585, 4.0489}, % C5' + {4.6841, -7.2019, 4.9443}, % H5' + {3.6189, -5.8889, 4.1625}, % H5'' + {5.6255, -5.9175, 3.5998}, % C4' + {5.8732, -5.1228, 4.3034}, % H4' + {6.7337, -6.8605, 3.5222}, % O4' + {7.5932, -6.4923, 2.4548}, % C1' + {8.5661, -6.2983, 2.9064}, % H1' + {7.0527, -5.2012, 1.8322}, % C2' + {7.1627, -5.2525, 0.7490}, % H2'' + {7.6666, -4.1249, 2.4880}, % O2' + {8.5944, -4.2543, 2.6981}, % H2' + {5.5661, -5.3029, 2.2009}, % C3' + {5.0841, -6.0018, 1.5172}, % H3' + {4.9062, -4.0452, 2.2042}, % O3' + {7.6298, -7.6136, 1.4752}, % N1 + {8.5977, -9.5977, 0.7329}, % N3 + {8.5951, -8.5745, 1.6594}, % C2 + {7.7372, -9.7371, -0.3364}, % C4 + {6.7596, -8.6801, -0.4476}, % C5 + {6.7338, -7.6721, 0.4408}, % C6 + c, { + {7.8849, -10.7881, -1.1289}, % N4 + {9.3993, -8.5377, 2.5743}, % O2 + {7.2499, -10.8809, -1.9088}, % H41 + {8.6122, -11.4649, -0.9468}, % H42 + {6.0317, -8.6941, -1.2588}, % H5 + {5.9901, -6.8809, 0.3459}} % H6 + }. + +rC06() -> + { + {-0.9837, 0.0476, -0.1733, % dgf_base_tfo + -0.1792, -0.3353, 0.9249, + -0.0141, 0.9409, 0.3384, + 5.7793, -5.2303, 4.5997}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {3.9938, -6.7042, 1.9023}, % C5' + {3.2332, -5.9343, 2.0319}, % H5' + {3.9666, -7.2863, 0.9812}, % H5'' + {5.3098, -5.9546, 1.8564}, % C4' + {5.3863, -5.3702, 0.9395}, % H4' + {5.3851, -5.0642, 3.0076}, % O4' + {6.7315, -4.9724, 3.4462}, % C1' + {7.0033, -3.9202, 3.3619}, % H1' + {7.5997, -5.8018, 2.4948}, % C2' + {8.3627, -6.3254, 3.0707}, % H2'' + {8.0410, -4.9501, 1.4724}, % O2' + {8.2781, -4.0644, 1.7570}, % H2' + {6.5701, -6.8129, 1.9714}, % C3' + {6.4186, -7.5809, 2.7299}, % H3' + {6.9357, -7.3841, 0.7235}, % O3' + {6.8024, -5.4718, 4.8475}, % N1 + {6.6920, -5.0495, 7.1354}, % N3 + {6.6201, -4.5500, 5.8506}, % C2 + {6.9254, -6.3614, 7.4926}, % C4 + {7.1046, -7.2543, 6.3718}, % C5 + {7.0391, -6.7951, 5.1106}, % C6 + c, { + {6.9614, -6.6648, 8.7815}, % N4 + {6.4083, -3.3696, 5.6340}, % O2 + {7.1329, -7.6280, 9.0324}, % H41 + {6.8204, -5.9469, 9.4777}, % H42 + {7.2954, -8.3135, 6.5440}, % H5 + {7.1753, -7.4798, 4.2735}} % H6 + }. + +rC07() -> + { + {0.0033, 0.2720, -0.9623, % dgf_base_tfo + 0.3013, -0.9179, -0.2584, + -0.9535, -0.2891, -0.0850, + 43.0403, 13.7233, 34.5710}, + {0.9187, 0.2887, 0.2694, % p_o3'_275_tfo + 0.0302, -0.7316, 0.6811, + 0.3938, -0.6176, -0.6808, + -48.4330, 26.3254, 13.6383}, + {-0.1504, 0.7744, -0.6145, % p_o3'_180_tfo + 0.7581, 0.4893, 0.4311, + 0.6345, -0.4010, -0.6607, + -31.9784, -13.4285, 44.9650}, + {-0.6236, -0.7810, -0.0337, % p_o3'_60_tfo + -0.6890, 0.5694, -0.4484, + 0.3694, -0.2564, -0.8932, + 12.1105, 30.8774, 46.0946}, + {33.3400, 11.0980, 46.1750}, % P + {34.5130, 10.2320, 46.4660}, % O1P + {33.4130, 12.3960, 46.9340}, % O2P + {31.9810, 10.3390, 46.4820}, % O5' + {30.8152, 11.1619, 46.2003}, % C5' + {30.4519, 10.9454, 45.1957}, % H5' + {31.0379, 12.2016, 46.4400}, % H5'' + {29.7081, 10.7448, 47.1428}, % C4' + {28.8710, 11.4416, 47.0982}, % H4' + {29.2550, 9.4394, 46.8162}, % O4' + {29.3907, 8.5625, 47.9460}, % C1' + {28.4416, 8.5669, 48.4819}, % H1' + {30.4468, 9.2031, 48.7952}, % C2' + {31.4222, 8.9651, 48.3709}, % H2'' + {30.3701, 8.9157, 50.1624}, % O2' + {30.0652, 8.0304, 50.3740}, % H2' + {30.1622, 10.6879, 48.6120}, % C3' + {31.0952, 11.2399, 48.7254}, % H3' + {29.1076, 11.1535, 49.4702}, % O3' + {29.7883, 7.2209, 47.5235}, % N1 + {29.1825, 5.0438, 46.8275}, % N3 + {28.8008, 6.2912, 47.2263}, % C2 + {30.4888, 4.6890, 46.7186}, % C4 + {31.5034, 5.6405, 47.0249}, % C5 + {31.1091, 6.8691, 47.4156}, % C6 + c, { + {30.8109, 3.4584, 46.3336}, % N4 + {27.6171, 6.5989, 47.3189}, % O2 + {31.7923, 3.2301, 46.2638}, % H41 + {30.0880, 2.7857, 46.1215}, % H42 + {32.5542, 5.3634, 46.9395}, % H5 + {31.8523, 7.6279, 47.6603}} % H6 + }. + +rC08() -> + { + {0.0797, -0.6026, -0.7941, % dgf_base_tfo + 0.7939, 0.5201, -0.3150, + 0.6028, -0.6054, 0.5198, + -36.8341, 41.5293, 1.6628}, + {0.9187, 0.2887, 0.2694, % p_o3'_275_tfo + 0.0302, -0.7316, 0.6811, + 0.3938, -0.6176, -0.6808, + -48.4330, 26.3254, 13.6383}, + {-0.1504, 0.7744, -0.6145, % p_o3'_180_tfo + 0.7581, 0.4893, 0.4311, + 0.6345, -0.4010, -0.6607, + -31.9784, -13.4285, 44.9650}, + {-0.6236, -0.7810, -0.0337, % p_o3'_60_tfo + -0.6890, 0.5694, -0.4484, + 0.3694, -0.2564, -0.8932, + 12.1105, 30.8774, 46.0946}, + {33.3400, 11.0980, 46.1750}, % P + {34.5130, 10.2320, 46.4660}, % O1P + {33.4130, 12.3960, 46.9340}, % O2P + {31.9810, 10.3390, 46.4820}, % O5' + {31.8779, 9.9369, 47.8760}, % C5' + {31.3239, 10.6931, 48.4322}, % H5' + {32.8647, 9.6624, 48.2489}, % H5'' + {31.0429, 8.6773, 47.9401}, % C4' + {31.0779, 8.2331, 48.9349}, % H4' + {29.6956, 8.9669, 47.5983}, % O4' + {29.2784, 8.1700, 46.4782}, % C1' + {28.8006, 7.2731, 46.8722}, % H1' + {30.5544, 7.7940, 45.7875}, % C2' + {30.8837, 8.6410, 45.1856}, % H2'' + {30.5100, 6.6007, 45.0582}, % O2' + {29.6694, 6.4168, 44.6326}, % H2' + {31.5146, 7.5954, 46.9527}, % C3' + {32.5255, 7.8261, 46.6166}, % H3' + {31.3876, 6.2951, 47.5516}, % O3' + {28.3976, 8.9302, 45.5933}, % N1 + {26.2155, 9.6135, 44.9910}, % N3 + {27.0281, 8.8961, 45.8192}, % C2 + {26.7044, 10.3489, 43.9595}, % C4 + {28.1088, 10.3837, 43.7247}, % C5 + {28.8978, 9.6708, 44.5535}, % C6 + c, { + {25.8715, 11.0249, 43.1749}, % N4 + {26.5733, 8.2371, 46.7484}, % O2 + {26.2707, 11.5609, 42.4177}, % H41 + {24.8760, 10.9939, 43.3427}, % H42 + {28.5089, 10.9722, 42.8990}, % H5 + {29.9782, 9.6687, 44.4097}} % H6 + }. + +rC09() -> + { + {0.8727, 0.4760, -0.1091, % dgf_base_tfo + -0.4188, 0.6148, -0.6682, + -0.2510, 0.6289, 0.7359, + -8.1687, -52.0761, -25.0726}, + {0.9187, 0.2887, 0.2694, % p_o3'_275_tfo + 0.0302, -0.7316, 0.6811, + 0.3938, -0.6176, -0.6808, + -48.4330, 26.3254, 13.6383}, + {-0.1504, 0.7744, -0.6145, % p_o3'_180_tfo + 0.7581, 0.4893, 0.4311, + 0.6345, -0.4010, -0.6607, + -31.9784, -13.4285, 44.9650}, + {-0.6236, -0.7810, -0.0337, % p_o3'_60_tfo + -0.6890, 0.5694, -0.4484, + 0.3694, -0.2564, -0.8932, + 12.1105, 30.8774, 46.0946}, + {33.3400, 11.0980, 46.1750}, % P + {34.5130, 10.2320, 46.4660}, % O1P + {33.4130, 12.3960, 46.9340}, % O2P + {31.9810, 10.3390, 46.4820}, % O5' + {30.8152, 11.1619, 46.2003}, % C5' + {30.4519, 10.9454, 45.1957}, % H5' + {31.0379, 12.2016, 46.4400}, % H5'' + {29.7081, 10.7448, 47.1428}, % C4' + {29.4506, 9.6945, 47.0059}, % H4' + {30.1045, 10.9634, 48.4885}, % O4' + {29.1794, 11.8418, 49.1490}, % C1' + {28.4388, 11.2210, 49.6533}, % H1' + {28.5211, 12.6008, 48.0367}, % C2' + {29.1947, 13.3949, 47.7147}, % H2'' + {27.2316, 13.0683, 48.3134}, % O2' + {27.0851, 13.3391, 49.2227}, % H2' + {28.4131, 11.5507, 46.9391}, % C3' + {28.4451, 12.0512, 45.9713}, % H3' + {27.2707, 10.6955, 47.1097}, % O3' + {29.8751, 12.7405, 50.0682}, % N1 + {30.7172, 13.1841, 52.2328}, % N3 + {30.0617, 12.3404, 51.3847}, % C2 + {31.1834, 14.3941, 51.8297}, % C4 + {30.9913, 14.8074, 50.4803}, % C5 + {30.3434, 13.9610, 49.6548}, % C6 + c, { + {31.8090, 15.1847, 52.6957}, % N4 + {29.6470, 11.2494, 51.7616}, % O2 + {32.1422, 16.0774, 52.3606}, % H41 + {31.9392, 14.8893, 53.6527}, % H42 + {31.3632, 15.7771, 50.1491}, % H5 + {30.1742, 14.2374, 48.6141}} % H6 + }. + +rC10() -> + { + {0.1549, 0.8710, -0.4663, % dgf_base_tfo + 0.6768, -0.4374, -0.5921, + -0.7197, -0.2239, -0.6572, + 25.2447, -14.1920, 50.3201}, + {0.9187, 0.2887, 0.2694, % p_o3'_275_tfo + 0.0302, -0.7316, 0.6811, + 0.3938, -0.6176, -0.6808, + -48.4330, 26.3254, 13.6383}, + {-0.1504, 0.7744, -0.6145, % p_o3'_180_tfo + 0.7581, 0.4893, 0.4311, + 0.6345, -0.4010, -0.6607, + -31.9784, -13.4285, 44.9650}, + {-0.6236, -0.7810, -0.0337, % p_o3'_60_tfo + -0.6890, 0.5694, -0.4484, + 0.3694, -0.2564, -0.8932, + 12.1105, 30.8774, 46.0946}, + {33.3400, 11.0980, 46.1750}, % P + {34.5130, 10.2320, 46.4660}, % O1P + {33.4130, 12.3960, 46.9340}, % O2P + {31.9810, 10.3390, 46.4820}, % O5' + {31.8779, 9.9369, 47.8760}, % C5' + {31.3239, 10.6931, 48.4322}, % H5' + {32.8647, 9.6624, 48.2489}, % H5'' + {31.0429, 8.6773, 47.9401}, % C4' + {30.0440, 8.8473, 47.5383}, % H4' + {31.6749, 7.6351, 47.2119}, % O4' + {31.9159, 6.5022, 48.0616}, % C1' + {31.0691, 5.8243, 47.9544}, % H1' + {31.9300, 7.0685, 49.4493}, % C2' + {32.9024, 7.5288, 49.6245}, % H2'' + {31.5672, 6.1750, 50.4632}, % O2' + {31.8416, 5.2663, 50.3200}, % H2' + {30.8618, 8.1514, 49.3749}, % C3' + {31.1122, 8.9396, 50.0850}, % H3' + {29.5351, 7.6245, 49.5409}, % O3' + {33.1890, 5.8629, 47.7343}, % N1 + {34.4004, 4.2636, 46.4828}, % N3 + {33.2062, 4.8497, 46.7851}, % C2 + {35.5600, 4.6374, 47.0822}, % C4 + {35.5444, 5.6751, 48.0577}, % C5 + {34.3565, 6.2450, 48.3432}, % C6 + c, { + {36.6977, 4.0305, 46.7598}, % N4 + {32.1661, 4.5034, 46.2348}, % O2 + {37.5405, 4.3347, 47.2259}, % H41 + {36.7033, 3.2923, 46.0706}, % H42 + {36.4713, 5.9811, 48.5428}, % H5 + {34.2986, 7.0426, 49.0839}} % H6 + }. + +rCs() -> [rC01(),rC02(),rC03(),rC04(),rC05(),rC06(),rC07(), + rC08(),rC09(),rC10()]. + +rG() -> + { + {-0.0018, -0.8207, 0.5714, % dgf_base_tfo + 0.2679, -0.5509, -0.7904, + 0.9634, 0.1517, 0.2209, + 0.0073, 8.4030, 0.6232}, + {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo + -0.0433, -0.4257, 0.9038, + -0.5788, 0.7480, 0.3246, + 1.5227, 6.9114, -7.0765}, + {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo + 0.4552, 0.6637, 0.5935, + -0.8042, 0.0203, 0.5941, + -6.9472, -4.1186, -5.9108}, + {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo + -0.8247, 0.5587, -0.0878, + 0.0426, 0.2162, 0.9754, + 6.2694, -7.0540, 3.3316}, + {2.8930, 8.5380, -3.3280}, % P + {1.6980, 7.6960, -3.5570}, % O1P + {3.2260, 9.5010, -4.4020}, % O2P + {4.1590, 7.6040, -3.0340}, % O5' + {5.4550, 8.2120, -2.8810}, % C5' + {5.4546, 8.8508, -1.9978}, % H5' + {5.7588, 8.6625, -3.8259}, % H5'' + {6.4970, 7.1480, -2.5980}, % C4' + {7.4896, 7.5919, -2.5214}, % H4' + {6.1630, 6.4860, -1.3440}, % O4' + {6.5400, 5.1200, -1.4190}, % C1' + {7.2763, 4.9681, -0.6297}, % H1' + {7.1940, 4.8830, -2.7770}, % C2' + {6.8667, 3.9183, -3.1647}, % H2'' + {8.5860, 5.0910, -2.6140}, % O2' + {8.9510, 4.7626, -1.7890}, % H2' + {6.5720, 6.0040, -3.6090}, % C3' + {5.5636, 5.7066, -3.8966}, % H3' + {7.3801, 6.3562, -4.7350}, % O3' + {4.7150, 0.4910, -0.1360}, % N1 + {6.3490, 2.1730, -0.6020}, % N3 + {5.9530, 0.9650, -0.2670}, % C2 + {5.2900, 2.9790, -0.8260}, % C4 + {3.9720, 2.6390, -0.7330}, % C5 + {3.6770, 1.3160, -0.3660}, % C6 + g, { + {6.8426, 0.0056, -0.0019}, % N2 + {3.1660, 3.7290, -1.0360}, % N7 + {5.3170, 4.2990, -1.1930}, % N9 + {4.0100, 4.6780, -1.2990}, % C8 + {2.4280, 0.8450, -0.2360}, % O6 + {4.6151, -0.4677, 0.1305}, % H1 + {6.6463, -0.9463, 0.2729}, % H21 + {7.8170, 0.2642, -0.0640}, % H22 + {3.4421, 5.5744, -1.5482}} % H8 + }. + +% rG01() -> +% { +% {-0.0043, -0.8175, 0.5759, % dgf_base_tfo +% 0.2617, -0.5567, -0.7884, +% 0.9651, 0.1473, 0.2164, +% 0.0359, 8.3929, 0.5532}, +% {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo +% -0.0433, -0.4257, 0.9038, +% -0.5788, 0.7480, 0.3246, +% 1.5227, 6.9114, -7.0765}, +% {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo +% 0.4552, 0.6637, 0.5935, +% -0.8042, 0.0203, 0.5941, +% -6.9472, -4.1186, -5.9108}, +% {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo +% -0.8247, 0.5587, -0.0878, +% 0.0426, 0.2162, 0.9754, +% 6.2694, -7.0540, 3.3316}, +% {2.8930, 8.5380, -3.3280}, % P +% {1.6980, 7.6960, -3.5570}, % O1P +% {3.2260, 9.5010, -4.4020}, % O2P +% {4.1590, 7.6040, -3.0340}, % O5' +% {5.4352, 8.2183, -2.7757}, % C5' +% {5.3830, 8.7883, -1.8481}, % H5' +% {5.7729, 8.7436, -3.6691}, % H5'' +% {6.4830, 7.1518, -2.5252}, % C4' +% {7.4749, 7.5972, -2.4482}, % H4' +% {6.1626, 6.4620, -1.2827}, % O4' +% {6.5431, 5.0992, -1.3905}, % C1' +% {7.2871, 4.9328, -0.6114}, % H1' +% {7.1852, 4.8935, -2.7592}, % C2' +% {6.8573, 3.9363, -3.1645}, % H2'' +% {8.5780, 5.1025, -2.6046}, % O2' +% {8.9516, 4.7577, -1.7902}, % H2' +% {6.5522, 6.0300, -3.5612}, % C3' +% {5.5420, 5.7356, -3.8459}, % H3' +% {7.3487, 6.4089, -4.6867}, % O3' +% {4.7442, 0.4514, -0.1390}, % N1 +% {6.3687, 2.1459, -0.5926}, % N3 +% {5.9795, 0.9335, -0.2657}, % C2 +% {5.3052, 2.9471, -0.8125}, % C4 +% {3.9891, 2.5987, -0.7230}, % C5 +% {3.7016, 1.2717, -0.3647}, % C6 +% g, { +% {6.8745, -0.0224, -0.0058}, % N2 +% {3.1770, 3.6859, -1.0198}, % N7 +% {5.3247, 4.2695, -1.1710}, % N9 +% {4.0156, 4.6415, -1.2759}, % C8 +% {2.4553, 0.7925, -0.2390}, % O6 +% {4.6497, -0.5095, 0.1212}, % H1 +% {6.6836, -0.9771, 0.2627}, % H21 +% {7.8474, 0.2424, -0.0653}, % H22 +% {3.4426, 5.5361, -1.5199}} % H8 +% }. + +% rG02() -> +% { +% {0.5566, 0.0449, 0.8296, % dgf_base_tfo +% 0.5125, 0.7673, -0.3854, +% -0.6538, 0.6397, 0.4041, +% -9.1161, -3.7679, -2.9968}, +% {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo +% -0.0433, -0.4257, 0.9038, +% -0.5788, 0.7480, 0.3246, +% 1.5227, 6.9114, -7.0765}, +% {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo +% 0.4552, 0.6637, 0.5935, +% -0.8042, 0.0203, 0.5941, +% -6.9472, -4.1186, -5.9108}, +% {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo +% -0.8247, 0.5587, -0.0878, +% 0.0426, 0.2162, 0.9754, +% 6.2694, -7.0540, 3.3316}, +% {2.8930, 8.5380, -3.3280}, % P +% {1.6980, 7.6960, -3.5570}, % O1P +% {3.2260, 9.5010, -4.4020}, % O2P +% {4.1590, 7.6040, -3.0340}, % O5' +% {4.5778, 6.6594, -4.0364}, % C5' +% {4.9220, 7.1963, -4.9204}, % H5' +% {3.7996, 5.9091, -4.1764}, % H5'' +% {5.7873, 5.8869, -3.5482}, % C4' +% {6.0405, 5.0875, -4.2446}, % H4' +% {6.9135, 6.8036, -3.4310}, % O4' +% {7.7293, 6.4084, -2.3392}, % C1' +% {8.7078, 6.1815, -2.7624}, % H1' +% {7.1305, 5.1418, -1.7347}, % C2' +% {7.2040, 5.1982, -0.6486}, % H2'' +% {7.7417, 4.0392, -2.3813}, % O2' +% {8.6785, 4.1443, -2.5630}, % H2' +% {5.6666, 5.2728, -2.1536}, % C3' +% {5.1747, 5.9805, -1.4863}, % H3' +% {4.9997, 4.0086, -2.1973}, % O3' +% {10.3245, 8.5459, 1.5467}, % N1 +% {9.8051, 6.9432, -0.1497}, % N3 +% {10.5175, 7.4328, 0.8408}, % C2 +% {8.7523, 7.7422, -0.4228}, % C4 +% {8.4257, 8.9060, 0.2099}, % C5 +% {9.2665, 9.3242, 1.2540}, % C6 +% g, { +% {11.6077, 6.7966, 1.2752}, % N2 +% {7.2750, 9.4537, -0.3428}, % N7 +% {7.7962, 7.5519, -1.3859}, % N9 +% {6.9479, 8.6157, -1.2771}, % C8 +% {9.0664, 10.4462, 1.9610}, % O6 +% {10.9838, 8.7524, 2.2697}, % H1 +% {12.2274, 7.0896, 2.0170}, % H21 +% {11.8502, 5.9398, 0.7984}, % H22 +% {6.0430, 8.9853, -1.7594}} % H8 +% }. + +% rG03() -> +% { +% {-0.5021, 0.0731, 0.8617, % dgf_base_tfo +% -0.8112, 0.3054, -0.4986, +% -0.2996, -0.9494, -0.0940, +% 6.4273, -5.1944, -3.7807}, +% {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo +% -0.0433, -0.4257, 0.9038, +% -0.5788, 0.7480, 0.3246, +% 1.5227, 6.9114, -7.0765}, +% {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo +% 0.4552, 0.6637, 0.5935, +% -0.8042, 0.0203, 0.5941, +% -6.9472, -4.1186, -5.9108}, +% {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo +% -0.8247, 0.5587, -0.0878, +% 0.0426, 0.2162, 0.9754, +% 6.2694, -7.0540, 3.3316}, +% {2.8930, 8.5380, -3.3280}, % P +% {1.6980, 7.6960, -3.5570}, % O1P +% {3.2260, 9.5010, -4.4020}, % O2P +% {4.1590, 7.6040, -3.0340}, % O5' +% {4.1214, 6.7116, -1.9049}, % C5' +% {3.3465, 5.9610, -2.0607}, % H5' +% {4.0789, 7.2928, -0.9837}, % H5'' +% {5.4170, 5.9293, -1.8186}, % C4' +% {5.4506, 5.3400, -0.9023}, % H4' +% {5.5067, 5.0417, -2.9703}, % O4' +% {6.8650, 4.9152, -3.3612}, % C1' +% {7.1090, 3.8577, -3.2603}, % H1' +% {7.7152, 5.7282, -2.3894}, % C2' +% {8.5029, 6.2356, -2.9463}, % H2'' +% {8.1036, 4.8568, -1.3419}, % O2' +% {8.3270, 3.9651, -1.6184}, % H2' +% {6.7003, 6.7565, -1.8911}, % C3' +% {6.5898, 7.5329, -2.6482}, % H3' +% {7.0505, 7.2878, -0.6105}, % O3' +% {9.6740, 4.7656, -7.6614}, % N1 +% {9.0739, 4.3013, -5.3941}, % N3 +% {9.8416, 4.2192, -6.4581}, % C2 +% {7.9885, 5.0632, -5.6446}, % C4 +% {7.6822, 5.6856, -6.8194}, % C5 +% {8.5831, 5.5215, -7.8840}, % C6 +% g, { +% {10.9733, 3.5117, -6.4286}, % N2 +% {6.4857, 6.3816, -6.7035}, % N7 +% {6.9740, 5.3703, -4.7760}, % N9 +% {6.1133, 6.1613, -5.4808}, % C8 +% {8.4084, 6.0747, -9.0933}, % O6 +% {10.3759, 4.5855, -8.3504}, % H1 +% {11.6254, 3.3761, -7.1879}, % H21 +% {11.1917, 3.0460, -5.5593}, % H22 +% {5.1705, 6.6830, -5.3167}} % H8 +% }. + +% rG04() -> +% { +% {-0.5426, -0.8175, 0.1929, % dgf_base_tfo +% 0.8304, -0.5567, -0.0237, +% 0.1267, 0.1473, 0.9809, +% -0.5075, 8.3929, 0.2229}, +% {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo +% -0.0433, -0.4257, 0.9038, +% -0.5788, 0.7480, 0.3246, +% 1.5227, 6.9114, -7.0765}, +% {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo +% 0.4552, 0.6637, 0.5935, +% -0.8042, 0.0203, 0.5941, +% -6.9472, -4.1186, -5.9108}, +% {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo +% -0.8247, 0.5587, -0.0878, +% 0.0426, 0.2162, 0.9754, +% 6.2694, -7.0540, 3.3316}, +% {2.8930, 8.5380, -3.3280}, % P +% {1.6980, 7.6960, -3.5570}, % O1P +% {3.2260, 9.5010, -4.4020}, % O2P +% {4.1590, 7.6040, -3.0340}, % O5' +% {5.4352, 8.2183, -2.7757}, % C5' +% {5.3830, 8.7883, -1.8481}, % H5' +% {5.7729, 8.7436, -3.6691}, % H5'' +% {6.4830, 7.1518, -2.5252}, % C4' +% {7.4749, 7.5972, -2.4482}, % H4' +% {6.1626, 6.4620, -1.2827}, % O4' +% {6.5431, 5.0992, -1.3905}, % C1' +% {7.2871, 4.9328, -0.6114}, % H1' +% {7.1852, 4.8935, -2.7592}, % C2' +% {6.8573, 3.9363, -3.1645}, % H2'' +% {8.5780, 5.1025, -2.6046}, % O2' +% {8.9516, 4.7577, -1.7902}, % H2' +% {6.5522, 6.0300, -3.5612}, % C3' +% {5.5420, 5.7356, -3.8459}, % H3' +% {7.3487, 6.4089, -4.6867}, % O3' +% {3.6343, 2.6680, 2.0783}, % N1 +% {5.4505, 3.9805, 1.2446}, % N3 +% {4.7540, 3.3816, 2.1851}, % C2 +% {4.8805, 3.7951, 0.0354}, % C4 +% {3.7416, 3.0925, -0.2305}, % C5 +% {3.0873, 2.4980, 0.8606}, % C6 +% g, { +% {5.1433, 3.4373, 3.4609}, % N2 +% {3.4605, 3.1184, -1.5906}, % N7 +% {5.3247, 4.2695, -1.1710}, % N9 +% {4.4244, 3.8244, -2.0953}, % C8 +% {1.9600, 1.7805, 0.7462}, % O6 +% {3.2489, 2.2879, 2.9191}, % H1 +% {4.6785, 3.0243, 4.2568}, % H21 +% {5.9823, 3.9654, 3.6539}, % H22 +% {4.2675, 3.8876, -3.1721}} % H8 +% }. + +% rG05() -> +% { +% {-0.5891, 0.0449, 0.8068, % dgf_base_tfo +% 0.5375, 0.7673, 0.3498, +% -0.6034, 0.6397, -0.4762, +% -0.3019, -3.7679, -9.5913}, +% {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo +% -0.0433, -0.4257, 0.9038, +% -0.5788, 0.7480, 0.3246, +% 1.5227, 6.9114, -7.0765}, +% {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo +% 0.4552, 0.6637, 0.5935, +% -0.8042, 0.0203, 0.5941, +% -6.9472, -4.1186, -5.9108}, +% {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo +% -0.8247, 0.5587, -0.0878, +% 0.0426, 0.2162, 0.9754, +% 6.2694, -7.0540, 3.3316}, +% {2.8930, 8.5380, -3.3280}, % P +% {1.6980, 7.6960, -3.5570}, % O1P +% {3.2260, 9.5010, -4.4020}, % O2P +% {4.1590, 7.6040, -3.0340}, % O5' +% {4.5778, 6.6594, -4.0364}, % C5' +% {4.9220, 7.1963, -4.9204}, % H5' +% {3.7996, 5.9091, -4.1764}, % H5'' +% {5.7873, 5.8869, -3.5482}, % C4' +% {6.0405, 5.0875, -4.2446}, % H4' +% {6.9135, 6.8036, -3.4310}, % O4' +% {7.7293, 6.4084, -2.3392}, % C1' +% {8.7078, 6.1815, -2.7624}, % H1' +% {7.1305, 5.1418, -1.7347}, % C2' +% {7.2040, 5.1982, -0.6486}, % H2'' +% {7.7417, 4.0392, -2.3813}, % O2' +% {8.6785, 4.1443, -2.5630}, % H2' +% {5.6666, 5.2728, -2.1536}, % C3' +% {5.1747, 5.9805, -1.4863}, % H3' +% {4.9997, 4.0086, -2.1973}, % O3' +% {10.2594, 10.6774, -1.0056}, % N1 +% {9.7528, 8.7080, -2.2631}, % N3 +% {10.4471, 9.7876, -1.9791}, % C2 +% {8.7271, 8.5575, -1.3991}, % C4 +% {8.4100, 9.3803, -0.3580}, % C5 +% {9.2294, 10.5030, -0.1574}, % C6 +% g, { +% {11.5110, 10.1256, -2.7114}, % N2 +% {7.2891, 8.9068, 0.3121}, % N7 +% {7.7962, 7.5519, -1.3859}, % N9 +% {6.9702, 7.8292, -0.3353}, % C8 +% {9.0349, 11.3951, 0.8250}, % O6 +% {10.9013, 11.4422, -0.9512}, % H1 +% {12.1031, 10.9341, -2.5861}, % H21 +% {11.7369, 9.5180, -3.4859}, % H22 +% {6.0888, 7.3990, 0.1403}} % H8 +% }. + +% rG06() -> +% { +% {-0.9815, 0.0731, -0.1772, % dgf_base_tfo +% 0.1912, 0.3054, -0.9328, +% -0.0141, -0.9494, -0.3137, +% 5.7506, -5.1944, 4.7470}, +% {-0.8143, -0.5091, -0.2788, % p_o3'_275_tfo +% -0.0433, -0.4257, 0.9038, +% -0.5788, 0.7480, 0.3246, +% 1.5227, 6.9114, -7.0765}, +% {0.3822, -0.7477, 0.5430, % p_o3'_180_tfo +% 0.4552, 0.6637, 0.5935, +% -0.8042, 0.0203, 0.5941, +% -6.9472, -4.1186, -5.9108}, +% {0.5640, 0.8007, -0.2022, % p_o3'_60_tfo +% -0.8247, 0.5587, -0.0878, +% 0.0426, 0.2162, 0.9754, +% 6.2694, -7.0540, 3.3316}, +% {2.8930, 8.5380, -3.3280}, % P +% {1.6980, 7.6960, -3.5570}, % O1P +% {3.2260, 9.5010, -4.4020}, % O2P +% {4.1590, 7.6040, -3.0340}, % O5' +% {4.1214, 6.7116, -1.9049}, % C5' +% {3.3465, 5.9610, -2.0607}, % H5' +% {4.0789, 7.2928, -0.9837}, % H5'' +% {5.4170, 5.9293, -1.8186}, % C4' +% {5.4506, 5.3400, -0.9023}, % H4' +% {5.5067, 5.0417, -2.9703}, % O4' +% {6.8650, 4.9152, -3.3612}, % C1' +% {7.1090, 3.8577, -3.2603}, % H1' +% {7.7152, 5.7282, -2.3894}, % C2' +% {8.5029, 6.2356, -2.9463}, % H2'' +% {8.1036, 4.8568, -1.3419}, % O2' +% {8.3270, 3.9651, -1.6184}, % H2' +% {6.7003, 6.7565, -1.8911}, % C3' +% {6.5898, 7.5329, -2.6482}, % H3' +% {7.0505, 7.2878, -0.6105}, % O3' +% {6.6624, 3.5061, -8.2986}, % N1 +% {6.5810, 3.2570, -5.9221}, % N3 +% {6.5151, 2.8263, -7.1625}, % C2 +% {6.8364, 4.5817, -5.8882}, % C4 +% {7.0116, 5.4064, -6.9609}, % C5 +% {6.9173, 4.8260, -8.2361}, % C6 +% g, { +% {6.2717, 1.5402, -7.4250}, % N2 +% {7.2573, 6.7070, -6.5394}, % N7 +% {6.9740, 5.3703, -4.7760}, % N9 +% {7.2238, 6.6275, -5.2453}, % C8 +% {7.0668, 5.5163, -9.3763}, % O6 +% {6.5754, 2.9964, -9.1545}, % H1 +% {6.1908, 1.1105, -8.3354}, % H21 +% {6.1346, 0.9352, -6.6280}, % H22 +% {7.4108, 7.6227, -4.8418}} % H8 +% }. + +% rG07() -> +% { +% {0.0894, -0.6059, 0.7905, % dgf_base_tfo +% -0.6810, 0.5420, 0.4924, +% -0.7268, -0.5824, -0.3642, +% 34.1424, 45.9610, -11.8600}, +% {-0.8644, -0.4956, -0.0851, % p_o3'_275_tfo +% -0.0427, 0.2409, -0.9696, +% 0.5010, -0.8345, -0.2294, +% 4.0167, 54.5377, 12.4779}, +% {0.3706, -0.6167, 0.6945, % p_o3'_180_tfo +% -0.2867, -0.7872, -0.5460, +% 0.8834, 0.0032, -0.4686, +% -52.9020, 18.6313, -0.6709}, +% {0.4155, 0.9025, -0.1137, % p_o3'_60_tfo +% 0.9040, -0.4236, -0.0582, +% -0.1007, -0.0786, -0.9918, +% -7.6624, -25.2080, 49.5181}, +% {31.3810, 0.1400, 47.5810}, % P +% {29.9860, 0.6630, 47.6290}, % O1P +% {31.7210, -0.6460, 48.8090}, % O2P +% {32.4940, 1.2540, 47.2740}, % O5' +% {33.8709, 0.7918, 47.2113}, % C5' +% {34.1386, 0.5870, 46.1747}, % H5' +% {34.0186, -0.0095, 47.9353}, % H5'' +% {34.7297, 1.9687, 47.6685}, % C4' +% {35.7723, 1.6845, 47.8113}, % H4' +% {34.6455, 2.9768, 46.6660}, % O4' +% {34.1690, 4.1829, 47.2627}, % C1' +% {35.0437, 4.7633, 47.5560}, % H1' +% {33.4145, 3.7532, 48.4954}, % C2' +% {32.4340, 3.3797, 48.2001}, % H2'' +% {33.3209, 4.6953, 49.5217}, % O2' +% {33.2374, 5.6059, 49.2295}, % H2' +% {34.2724, 2.5970, 48.9773}, % C3' +% {33.6373, 1.8935, 49.5157}, % H3' +% {35.3453, 3.1884, 49.7285}, % O3' +% {34.0511, 7.8930, 43.7791}, % N1 +% {34.9937, 6.3369, 45.3199}, % N3 +% {35.0882, 7.3126, 44.4200}, % C2 +% {33.7190, 5.9650, 45.5374}, % C4 +% {32.5845, 6.4770, 44.9458}, % C5 +% {32.7430, 7.5179, 43.9914}, % C6 +% g, { +% {36.3030, 7.7827, 44.1036}, % N2 +% {31.4499, 5.8335, 45.4368}, % N7 +% {33.2760, 4.9817, 46.4043}, % N9 +% {31.9235, 4.9639, 46.2934}, % C8 +% {31.8602, 8.1000, 43.3695}, % O6 +% {34.2623, 8.6223, 43.1283}, % H1 +% {36.5188, 8.5081, 43.4347}, % H21 +% {37.0888, 7.3524, 44.5699}, % H22 +% {31.0815, 4.4201, 46.7218}} % H8 +% }. + +% rG08() -> +% { +% {0.2224, 0.6335, 0.7411, % dgf_base_tfo +% -0.3644, -0.6510, 0.6659, +% 0.9043, -0.4181, 0.0861, +% -47.6824, -0.5823, -31.7554}, +% {-0.8644, -0.4956, -0.0851, % p_o3'_275_tfo +% -0.0427, 0.2409, -0.9696, +% 0.5010, -0.8345, -0.2294, +% 4.0167, 54.5377, 12.4779}, +% {0.3706, -0.6167, 0.6945, % p_o3'_180_tfo +% -0.2867, -0.7872, -0.5460, +% 0.8834, 0.0032, -0.4686, +% -52.9020, 18.6313, -0.6709}, +% {0.4155, 0.9025, -0.1137, % p_o3'_60_tfo +% 0.9040, -0.4236, -0.0582, +% -0.1007, -0.0786, -0.9918, +% -7.6624, -25.2080, 49.5181}, +% {31.3810, 0.1400, 47.5810}, % P +% {29.9860, 0.6630, 47.6290}, % O1P +% {31.7210, -0.6460, 48.8090}, % O2P +% {32.4940, 1.2540, 47.2740}, % O5' +% {32.5924, 2.3488, 48.2255}, % C5' +% {33.3674, 2.1246, 48.9584}, % H5' +% {31.5994, 2.5917, 48.6037}, % H5'' +% {33.0722, 3.5577, 47.4258}, % C4' +% {33.0310, 4.4778, 48.0089}, % H4' +% {34.4173, 3.3055, 47.0316}, % O4' +% {34.5056, 3.3910, 45.6094}, % C1' +% {34.7881, 4.4152, 45.3663}, % H1' +% {33.1122, 3.1198, 45.1010}, % C2' +% {32.9230, 2.0469, 45.1369}, % H2'' +% {32.7946, 3.6590, 43.8529}, % O2' +% {33.5170, 3.6707, 43.2207}, % H2' +% {32.2730, 3.8173, 46.1566}, % C3' +% {31.3094, 3.3123, 46.2244}, % H3' +% {32.2391, 5.2039, 45.7807}, % O3' +% {39.3337, 2.7157, 44.1441}, % N1 +% {37.4430, 3.8242, 45.0824}, % N3 +% {38.7276, 3.7646, 44.7403}, % C2 +% {36.7791, 2.6963, 44.7704}, % C4 +% {37.2860, 1.5653, 44.1678}, % C5 +% {38.6647, 1.5552, 43.8235}, % C6 +% g, { +% {39.5123, 4.8216, 44.9936}, % N2 +% {36.2829, 0.6110, 44.0078}, % N7 +% {35.4394, 2.4314, 44.9931}, % N9 +% {35.2180, 1.1815, 44.5128}, % C8 +% {39.2907, 0.6514, 43.2796}, % O6 +% {40.3076, 2.8048, 43.9352}, % H1 +% {40.4994, 4.9066, 44.7977}, % H21 +% {39.0738, 5.6108, 45.4464}, % H22 +% {34.3856, 0.4842, 44.4185}} % H8 +% }. + +% rG09() -> +% { +% {-0.9699, -0.1688, -0.1753, % dgf_base_tfo +% -0.1050, -0.3598, 0.9271, +% -0.2196, 0.9176, 0.3312, +% 45.6217, -38.9484, -12.3208}, +% {-0.8644, -0.4956, -0.0851, % p_o3'_275_tfo +% -0.0427, 0.2409, -0.9696, +% 0.5010, -0.8345, -0.2294, +% 4.0167, 54.5377, 12.4779}, +% {0.3706, -0.6167, 0.6945, % p_o3'_180_tfo +% -0.2867, -0.7872, -0.5460, +% 0.8834, 0.0032, -0.4686, +% -52.9020, 18.6313, -0.6709}, +% {0.4155, 0.9025, -0.1137, % p_o3'_60_tfo +% 0.9040, -0.4236, -0.0582, +% -0.1007, -0.0786, -0.9918, +% -7.6624, -25.2080, 49.5181}, +% {31.3810, 0.1400, 47.5810}, % P +% {29.9860, 0.6630, 47.6290}, % O1P +% {31.7210, -0.6460, 48.8090}, % O2P +% {32.4940, 1.2540, 47.2740}, % O5' +% {33.8709, 0.7918, 47.2113}, % C5' +% {34.1386, 0.5870, 46.1747}, % H5' +% {34.0186, -0.0095, 47.9353}, % H5'' +% {34.7297, 1.9687, 47.6685}, % C4' +% {34.5880, 2.8482, 47.0404}, % H4' +% {34.3575, 2.2770, 49.0081}, % O4' +% {35.5157, 2.1993, 49.8389}, % C1' +% {35.9424, 3.2010, 49.8893}, % H1' +% {36.4701, 1.2820, 49.1169}, % C2' +% {36.1545, 0.2498, 49.2683}, % H2'' +% {37.8262, 1.4547, 49.4008}, % O2' +% {38.0227, 1.6945, 50.3094}, % H2' +% {36.2242, 1.6797, 47.6725}, % C3' +% {36.4297, 0.8197, 47.0351}, % H3' +% {37.0289, 2.8480, 47.4426}, % O3' +% {34.3005, 3.5042, 54.6070}, % N1 +% {34.7693, 3.7936, 52.2874}, % N3 +% {34.4484, 4.2541, 53.4939}, % C2 +% {34.9354, 2.4584, 52.2785}, % C4 +% {34.8092, 1.5915, 53.3422}, % C5 +% {34.4646, 2.1367, 54.6085}, % C6 +% g, { +% {34.2514, 5.5708, 53.6503}, % N2 +% {35.0641, 0.2835, 52.9337}, % N7 +% {35.2669, 1.6690, 51.1915}, % N9 +% {35.3288, 0.3954, 51.6563}, % C8 +% {34.3151, 1.5317, 55.6650}, % O6 +% {34.0623, 3.9797, 55.4539}, % H1 +% {33.9950, 6.0502, 54.5016}, % H21 +% {34.3512, 6.1432, 52.8242}, % H22 +% {35.5414, -0.6006, 51.2679}} % H8 +% }. + +% rG10() -> +% { +% {-0.0980, -0.9723, 0.2122, % dgf_base_tfo +% -0.9731, 0.1383, 0.1841, +% -0.2083, -0.1885, -0.9597, +% 17.8469, 38.8265, 37.0475}, +% {-0.8644, -0.4956, -0.0851, % p_o3'_275_tfo +% -0.0427, 0.2409, -0.9696, +% 0.5010, -0.8345, -0.2294, +% 4.0167, 54.5377, 12.4779}, +% {0.3706, -0.6167, 0.6945, % p_o3'_180_tfo +% -0.2867, -0.7872, -0.5460, +% 0.8834, 0.0032, -0.4686, +% -52.9020, 18.6313, -0.6709}, +% {0.4155, 0.9025, -0.1137, % p_o3'_60_tfo +% 0.9040, -0.4236, -0.0582, +% -0.1007, -0.0786, -0.9918, +% -7.6624, -25.2080, 49.5181}, +% {31.3810, 0.1400, 47.5810}, % P +% {29.9860, 0.6630, 47.6290}, % O1P +% {31.7210, -0.6460, 48.8090}, % O2P +% {32.4940, 1.2540, 47.2740}, % O5' +% {32.5924, 2.3488, 48.2255}, % C5' +% {33.3674, 2.1246, 48.9584}, % H5' +% {31.5994, 2.5917, 48.6037}, % H5'' +% {33.0722, 3.5577, 47.4258}, % C4' +% {34.0333, 3.3761, 46.9447}, % H4' +% {32.0890, 3.8338, 46.4332}, % O4' +% {31.6377, 5.1787, 46.5914}, % C1' +% {32.2499, 5.8016, 45.9392}, % H1' +% {31.9167, 5.5319, 48.0305}, % C2' +% {31.1507, 5.0820, 48.6621}, % H2'' +% {32.0865, 6.8890, 48.3114}, % O2' +% {31.5363, 7.4819, 47.7942}, % H2' +% {33.2398, 4.8224, 48.2563}, % C3' +% {33.3166, 4.5570, 49.3108}, % H3' +% {34.2528, 5.7056, 47.7476}, % O3' +% {28.2782, 6.3049, 42.9364}, % N1 +% {30.4001, 5.8547, 43.9258}, % N3 +% {29.6195, 6.1568, 42.8913}, % C2 +% {29.7005, 5.7006, 45.0649}, % C4 +% {28.3383, 5.8221, 45.2343}, % C5 +% {27.5519, 6.1461, 44.0958}, % C6 +% g, { +% {30.1838, 6.3385, 41.6890}, % N2 +% {27.9936, 5.5926, 46.5651}, % N7 +% {30.2046, 5.3825, 46.3136}, % N9 +% {29.1371, 5.3398, 47.1506}, % C8 +% {26.3361, 6.3024, 44.0495}, % O6 +% {27.8122, 6.5394, 42.0833}, % H1 +% {29.7125, 6.5595, 40.8235}, % H21 +% {31.1859, 6.2231, 41.6389}, % H22 +% {28.9406, 5.1504, 48.2059}} % H8 +% }. + +% rGs() -> [rG01(),rG02(),rG03(),rG04(),rG05(),rG06(),rG07(), +% rG08(),rG09(),rG10()]. + +rU() -> + { + {-0.0359, -0.8071, 0.5894, % dgf_base_tfo + -0.2669, 0.5761, 0.7726, + -0.9631, -0.1296, -0.2361, + 0.1584, 8.3434, 0.5434}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {5.2430, -8.2420, 2.8260}, % C5' + {5.1974, -8.8497, 1.9223}, % H5' + {5.5548, -8.7348, 3.7469}, % H5'' + {6.3140, -7.2060, 2.5510}, % C4' + {7.2954, -7.6762, 2.4898}, % H4' + {6.0140, -6.5420, 1.2890}, % O4' + {6.4190, -5.1840, 1.3620}, % C1' + {7.1608, -5.0495, 0.5747}, % H1' + {7.0760, -4.9560, 2.7270}, % C2' + {6.7770, -3.9803, 3.1099}, % H2'' + {8.4500, -5.1930, 2.5810}, % O2' + {8.8309, -4.8755, 1.7590}, % H2' + {6.4060, -6.0590, 3.5580}, % C3' + {5.4021, -5.7313, 3.8281}, % H3' + {7.1570, -6.4240, 4.7070}, % O3' + {5.2170, -4.3260, 1.1690}, % N1 + {4.2960, -2.2560, 0.6290}, % N3 + {5.4330, -3.0200, 0.7990}, % C2 + {2.9930, -2.6780, 0.7940}, % C4 + {2.8670, -4.0630, 1.1830}, % C5 + {3.9570, -4.8300, 1.3550}, % C6 + u, { + {6.5470, -2.5560, 0.6290}, % O2 + {2.0540, -1.9000, 0.6130}, % O4 + {4.4300, -1.3020, 0.3600}, % H3 + {1.9590, -4.4570, 1.3250}, % H5 + {3.8460, -5.7860, 1.6240}} % H6 + }. + +rU01() -> + { + {-0.0137, -0.8012, 0.5983, % dgf_base_tfo + -0.2523, 0.5817, 0.7733, + -0.9675, -0.1404, -0.2101, + 0.2031, 8.3874, 0.4228}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {5.2416, -8.2422, 2.8181}, % C5' + {5.2050, -8.8128, 1.8901}, % H5' + {5.5368, -8.7738, 3.7227}, % H5'' + {6.3232, -7.2037, 2.6002}, % C4' + {7.3048, -7.6757, 2.5577}, % H4' + {6.0635, -6.5092, 1.3456}, % O4' + {6.4697, -5.1547, 1.4629}, % C1' + {7.2354, -5.0043, 0.7018}, % H1' + {7.0856, -4.9610, 2.8521}, % C2' + {6.7777, -3.9935, 3.2487}, % H2'' + {8.4627, -5.1992, 2.7423}, % O2' + {8.8693, -4.8638, 1.9399}, % H2' + {6.3877, -6.0809, 3.6362}, % C3' + {5.3770, -5.7562, 3.8834}, % H3' + {7.1024, -6.4754, 4.7985}, % O3' + {5.2764, -4.2883, 1.2538}, % N1 + {4.3777, -2.2062, 0.7229}, % N3 + {5.5069, -2.9779, 0.9088}, % C2 + {3.0693, -2.6246, 0.8500}, % C4 + {2.9279, -4.0146, 1.2149}, % C5 + {4.0101, -4.7892, 1.4017}, % C6 + u, { + {6.6267, -2.5166, 0.7728}, % O2 + {2.1383, -1.8396, 0.6581}, % O4 + {4.5223, -1.2489, 0.4716}, % H3 + {2.0151, -4.4065, 1.3290}, % H5 + {3.8886, -5.7486, 1.6535}} % H6 + }. + +rU02() -> + { + {0.5141, 0.0246, 0.8574, % dgf_base_tfo + -0.5547, -0.7529, 0.3542, + 0.6542, -0.6577, -0.3734, + -9.1111, -3.4598, -3.2939}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {4.3825, -6.6585, 4.0489}, % C5' + {4.6841, -7.2019, 4.9443}, % H5' + {3.6189, -5.8889, 4.1625}, % H5'' + {5.6255, -5.9175, 3.5998}, % C4' + {5.8732, -5.1228, 4.3034}, % H4' + {6.7337, -6.8605, 3.5222}, % O4' + {7.5932, -6.4923, 2.4548}, % C1' + {8.5661, -6.2983, 2.9064}, % H1' + {7.0527, -5.2012, 1.8322}, % C2' + {7.1627, -5.2525, 0.7490}, % H2'' + {7.6666, -4.1249, 2.4880}, % O2' + {8.5944, -4.2543, 2.6981}, % H2' + {5.5661, -5.3029, 2.2009}, % C3' + {5.0841, -6.0018, 1.5172}, % H3' + {4.9062, -4.0452, 2.2042}, % O3' + {7.6298, -7.6136, 1.4752}, % N1 + {8.6945, -8.7046, -0.2857}, % N3 + {8.6943, -7.6514, 0.6066}, % C2 + {7.7426, -9.6987, -0.3801}, % C4 + {6.6642, -9.5742, 0.5722}, % C5 + {6.6391, -8.5592, 1.4526}, % C6 + u, { + {9.5840, -6.8186, 0.6136}, % O2 + {7.8505, -10.5925, -1.2223}, % O4 + {9.4601, -8.7514, -0.9277}, % H3 + {5.9281, -10.2509, 0.5782}, % H5 + {5.8831, -8.4931, 2.1028}} % H6 + }. + +rU03() -> + { + {-0.4993, 0.0476, 0.8651, % dgf_base_tfo + 0.8078, -0.3353, 0.4847, + 0.3132, 0.9409, 0.1290, + 6.2989, -5.2303, -3.8577}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {3.9938, -6.7042, 1.9023}, % C5' + {3.2332, -5.9343, 2.0319}, % H5' + {3.9666, -7.2863, 0.9812}, % H5'' + {5.3098, -5.9546, 1.8564}, % C4' + {5.3863, -5.3702, 0.9395}, % H4' + {5.3851, -5.0642, 3.0076}, % O4' + {6.7315, -4.9724, 3.4462}, % C1' + {7.0033, -3.9202, 3.3619}, % H1' + {7.5997, -5.8018, 2.4948}, % C2' + {8.3627, -6.3254, 3.0707}, % H2'' + {8.0410, -4.9501, 1.4724}, % O2' + {8.2781, -4.0644, 1.7570}, % H2' + {6.5701, -6.8129, 1.9714}, % C3' + {6.4186, -7.5809, 2.7299}, % H3' + {6.9357, -7.3841, 0.7235}, % O3' + {6.8024, -5.4718, 4.8475}, % N1 + {7.9218, -5.5700, 6.8877}, % N3 + {7.8908, -5.0886, 5.5944}, % C2 + {6.9789, -6.3827, 7.4823}, % C4 + {5.8742, -6.7319, 6.6202}, % C5 + {5.8182, -6.2769, 5.3570}, % C6 + u, { + {8.7747, -4.3728, 5.1568}, % O2 + {7.1154, -6.7509, 8.6509}, % O4 + {8.7055, -5.3037, 7.4491}, % H3 + {5.1416, -7.3178, 6.9665}, % H5 + {5.0441, -6.5310, 4.7784}} % H6 + }. + +rU04() -> + { + {-0.5669, -0.8012, 0.1918, % dgf_base_tfo + -0.8129, 0.5817, 0.0273, + -0.1334, -0.1404, -0.9811, + -0.3279, 8.3874, 0.3355}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {5.2416, -8.2422, 2.8181}, % C5' + {5.2050, -8.8128, 1.8901}, % H5' + {5.5368, -8.7738, 3.7227}, % H5'' + {6.3232, -7.2037, 2.6002}, % C4' + {7.3048, -7.6757, 2.5577}, % H4' + {6.0635, -6.5092, 1.3456}, % O4' + {6.4697, -5.1547, 1.4629}, % C1' + {7.2354, -5.0043, 0.7018}, % H1' + {7.0856, -4.9610, 2.8521}, % C2' + {6.7777, -3.9935, 3.2487}, % H2'' + {8.4627, -5.1992, 2.7423}, % O2' + {8.8693, -4.8638, 1.9399}, % H2' + {6.3877, -6.0809, 3.6362}, % C3' + {5.3770, -5.7562, 3.8834}, % H3' + {7.1024, -6.4754, 4.7985}, % O3' + {5.2764, -4.2883, 1.2538}, % N1 + {3.8961, -3.0896, -0.1893}, % N3 + {5.0095, -3.8907, -0.0346}, % C2 + {3.0480, -2.6632, 0.8116}, % C4 + {3.4093, -3.1310, 2.1292}, % C5 + {4.4878, -3.9124, 2.3088}, % C6 + u, { + {5.7005, -4.2164, -0.9842}, % O2 + {2.0800, -1.9458, 0.5503}, % O4 + {3.6834, -2.7882, -1.1190}, % H3 + {2.8508, -2.8721, 2.9172}, % H5 + {4.7188, -4.2247, 3.2295}} % H6 + }. + +rU05() -> + { + {-0.6298, 0.0246, 0.7763, % dgf_base_tfo + -0.5226, -0.7529, -0.4001, + 0.5746, -0.6577, 0.4870, + -0.0208, -3.4598, -9.6882}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {4.3825, -6.6585, 4.0489}, % C5' + {4.6841, -7.2019, 4.9443}, % H5' + {3.6189, -5.8889, 4.1625}, % H5'' + {5.6255, -5.9175, 3.5998}, % C4' + {5.8732, -5.1228, 4.3034}, % H4' + {6.7337, -6.8605, 3.5222}, % O4' + {7.5932, -6.4923, 2.4548}, % C1' + {8.5661, -6.2983, 2.9064}, % H1' + {7.0527, -5.2012, 1.8322}, % C2' + {7.1627, -5.2525, 0.7490}, % H2'' + {7.6666, -4.1249, 2.4880}, % O2' + {8.5944, -4.2543, 2.6981}, % H2' + {5.5661, -5.3029, 2.2009}, % C3' + {5.0841, -6.0018, 1.5172}, % H3' + {4.9062, -4.0452, 2.2042}, % O3' + {7.6298, -7.6136, 1.4752}, % N1 + {8.5977, -9.5977, 0.7329}, % N3 + {8.5951, -8.5745, 1.6594}, % C2 + {7.7372, -9.7371, -0.3364}, % C4 + {6.7596, -8.6801, -0.4476}, % C5 + {6.7338, -7.6721, 0.4408}, % C6 + u, { + {9.3993, -8.5377, 2.5743}, % O2 + {7.8374, -10.6990, -1.1008}, % O4 + {9.2924, -10.3081, 0.8477}, % H3 + {6.0932, -8.6982, -1.1929}, % H5 + {6.0481, -6.9515, 0.3446}} % H6 + }. + +rU06() -> + { + {-0.9837, 0.0476, -0.1733, % dgf_base_tfo + -0.1792, -0.3353, 0.9249, + -0.0141, 0.9409, 0.3384, + 5.7793, -5.2303, 4.5997}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {3.9938, -6.7042, 1.9023}, % C5' + {3.2332, -5.9343, 2.0319}, % H5' + {3.9666, -7.2863, 0.9812}, % H5'' + {5.3098, -5.9546, 1.8564}, % C4' + {5.3863, -5.3702, 0.9395}, % H4' + {5.3851, -5.0642, 3.0076}, % O4' + {6.7315, -4.9724, 3.4462}, % C1' + {7.0033, -3.9202, 3.3619}, % H1' + {7.5997, -5.8018, 2.4948}, % C2' + {8.3627, -6.3254, 3.0707}, % H2'' + {8.0410, -4.9501, 1.4724}, % O2' + {8.2781, -4.0644, 1.7570}, % H2' + {6.5701, -6.8129, 1.9714}, % C3' + {6.4186, -7.5809, 2.7299}, % H3' + {6.9357, -7.3841, 0.7235}, % O3' + {6.8024, -5.4718, 4.8475}, % N1 + {6.6920, -5.0495, 7.1354}, % N3 + {6.6201, -4.5500, 5.8506}, % C2 + {6.9254, -6.3614, 7.4926}, % C4 + {7.1046, -7.2543, 6.3718}, % C5 + {7.0391, -6.7951, 5.1106}, % C6 + u, { + {6.4083, -3.3696, 5.6340}, % O2 + {6.9679, -6.6901, 8.6800}, % O4 + {6.5626, -4.3957, 7.8812}, % H3 + {7.2781, -8.2254, 6.5350}, % H5 + {7.1657, -7.4312, 4.3503}} % H6 + }. + +rU07() -> + { + {-0.9434, 0.3172, 0.0971, % dgf_base_tfo + 0.2294, 0.4125, 0.8816, + 0.2396, 0.8539, -0.4619, + 8.3625, -52.7147, 1.3745}, + {0.2765, -0.1121, -0.9545, % p_o3'_275_tfo + -0.8297, 0.4733, -0.2959, + 0.4850, 0.8737, 0.0379, + -14.7774, -45.2464, 21.9088}, + {0.1063, -0.6334, -0.7665, % p_o3'_180_tfo + -0.5932, -0.6591, 0.4624, + -0.7980, 0.4055, -0.4458, + 43.7634, 4.3296, 28.4890}, + {0.7136, -0.5032, -0.4873, % p_o3'_60_tfo + 0.6803, 0.3317, 0.6536, + -0.1673, -0.7979, 0.5791, + -17.1858, 41.4390, -27.0751}, + {21.3880, 15.0780, 45.5770}, % P + {21.9980, 14.5500, 46.8210}, % O1P + {21.1450, 14.0270, 44.5420}, % O2P + {22.1250, 16.3600, 44.9460}, % O5' + {21.5037, 16.8594, 43.7323}, % C5' + {20.8147, 17.6663, 43.9823}, % H5' + {21.1086, 16.0230, 43.1557}, % H5'' + {22.5654, 17.4874, 42.8616}, % C4' + {22.1584, 17.7243, 41.8785}, % H4' + {23.0557, 18.6826, 43.4751}, % O4' + {24.4788, 18.6151, 43.6455}, % C1' + {24.9355, 19.0840, 42.7739}, % H1' + {24.7958, 17.1427, 43.6474}, % C2' + {24.5652, 16.7400, 44.6336}, % H2'' + {26.1041, 16.8773, 43.2455}, % O2' + {26.7516, 17.5328, 43.5149}, % H2' + {23.8109, 16.5979, 42.6377}, % C3' + {23.5756, 15.5686, 42.9084}, % H3' + {24.2890, 16.7447, 41.2729}, % O3' + {24.9420, 19.2174, 44.8923}, % N1 + {25.2655, 20.5636, 44.8883}, % N3 + {25.1663, 21.2219, 43.8561}, % C2 + {25.6911, 21.1219, 46.0494}, % C4 + {25.8051, 20.4068, 47.2048}, % C5 + {26.2093, 20.9962, 48.2534}, % C6 + u, { + {25.4692, 19.0221, 47.2053}, % O2 + {25.0502, 18.4827, 46.0370}, % O4 + {25.9599, 22.1772, 46.0966}, % H3 + {25.5545, 18.4409, 48.1234}, % H5 + {24.7854, 17.4265, 45.9883}} % H6 + }. + +rU08() -> + { + {-0.0080, -0.7928, 0.6094, % dgf_base_tfo + -0.7512, 0.4071, 0.5197, + -0.6601, -0.4536, -0.5988, + 44.1482, 30.7036, 2.1088}, + {0.2765, -0.1121, -0.9545, % p_o3'_275_tfo + -0.8297, 0.4733, -0.2959, + 0.4850, 0.8737, 0.0379, + -14.7774, -45.2464, 21.9088}, + {0.1063, -0.6334, -0.7665, % p_o3'_180_tfo + -0.5932, -0.6591, 0.4624, + -0.7980, 0.4055, -0.4458, + 43.7634, 4.3296, 28.4890}, + {0.7136, -0.5032, -0.4873, % p_o3'_60_tfo + 0.6803, 0.3317, 0.6536, + -0.1673, -0.7979, 0.5791, + -17.1858, 41.4390, -27.0751}, + {21.3880, 15.0780, 45.5770}, % P + {21.9980, 14.5500, 46.8210}, % O1P + {21.1450, 14.0270, 44.5420}, % O2P + {22.1250, 16.3600, 44.9460}, % O5' + {23.5096, 16.1227, 44.5783}, % C5' + {23.5649, 15.8588, 43.5222}, % H5' + {23.9621, 15.4341, 45.2919}, % H5'' + {24.2805, 17.4138, 44.7151}, % C4' + {25.3492, 17.2309, 44.6030}, % H4' + {23.8497, 18.3471, 43.7208}, % O4' + {23.4090, 19.5681, 44.3321}, % C1' + {24.2595, 20.2496, 44.3524}, % H1' + {23.0418, 19.1813, 45.7407}, % C2' + {22.0532, 18.7224, 45.7273}, % H2'' + {23.1307, 20.2521, 46.6291}, % O2' + {22.8888, 21.1051, 46.2611}, % H2' + {24.0799, 18.1326, 46.0700}, % C3' + {23.6490, 17.4370, 46.7900}, % H3' + {25.3329, 18.7227, 46.5109}, % O3' + {22.2515, 20.1624, 43.6698}, % N1 + {22.4760, 21.0609, 42.6406}, % N3 + {23.6229, 21.3462, 42.3061}, % C2 + {21.3986, 21.6081, 42.0236}, % C4 + {20.1189, 21.3012, 42.3804}, % C5 + {19.1599, 21.8516, 41.7578}, % C6 + u, { + {19.8919, 20.3745, 43.4387}, % O2 + {20.9790, 19.8423, 44.0440}, % O4 + {21.5235, 22.3222, 41.2097}, % H3 + {18.8732, 20.1200, 43.7312}, % H5 + {20.8545, 19.1313, 44.8608}} % H6 + }. + +rU09() -> + { + {-0.0317, 0.1374, 0.9900, % dgf_base_tfo + -0.3422, -0.9321, 0.1184, + 0.9391, -0.3351, 0.0765, + -32.1929, 25.8198, -28.5088}, + {0.2765, -0.1121, -0.9545, % p_o3'_275_tfo + -0.8297, 0.4733, -0.2959, + 0.4850, 0.8737, 0.0379, + -14.7774, -45.2464, 21.9088}, + {0.1063, -0.6334, -0.7665, % p_o3'_180_tfo + -0.5932, -0.6591, 0.4624, + -0.7980, 0.4055, -0.4458, + 43.7634, 4.3296, 28.4890}, + {0.7136, -0.5032, -0.4873, % p_o3'_60_tfo + 0.6803, 0.3317, 0.6536, + -0.1673, -0.7979, 0.5791, + -17.1858, 41.4390, -27.0751}, + {21.3880, 15.0780, 45.5770}, % P + {21.9980, 14.5500, 46.8210}, % O1P + {21.1450, 14.0270, 44.5420}, % O2P + {22.1250, 16.3600, 44.9460}, % O5' + {21.5037, 16.8594, 43.7323}, % C5' + {20.8147, 17.6663, 43.9823}, % H5' + {21.1086, 16.0230, 43.1557}, % H5'' + {22.5654, 17.4874, 42.8616}, % C4' + {23.0565, 18.3036, 43.3915}, % H4' + {23.5375, 16.5054, 42.4925}, % O4' + {23.6574, 16.4257, 41.0649}, % C1' + {24.4701, 17.0882, 40.7671}, % H1' + {22.3525, 16.9643, 40.5396}, % C2' + {21.5993, 16.1799, 40.6133}, % H2'' + {22.4693, 17.4849, 39.2515}, % O2' + {23.0899, 17.0235, 38.6827}, % H2' + {22.0341, 18.0633, 41.5279}, % C3' + {20.9509, 18.1709, 41.5846}, % H3' + {22.7249, 19.3020, 41.2100}, % O3' + {23.8580, 15.0648, 40.5757}, % N1 + {25.1556, 14.5982, 40.4523}, % N3 + {26.1047, 15.3210, 40.7448}, % C2 + {25.3391, 13.3315, 40.0020}, % C4 + {24.2974, 12.5148, 39.6749}, % C5 + {24.5450, 11.3410, 39.2610}, % C6 + u, { + {22.9633, 12.9979, 39.8053}, % O2 + {22.8009, 14.2648, 40.2524}, % O4 + {26.3414, 12.9194, 39.8855}, % H3 + {22.1227, 12.3533, 39.5486}, % H5 + {21.7989, 14.6788, 40.3650}} % H6 + }. + +rU10() -> + { + {-0.9674, 0.1021, -0.2318, % dgf_base_tfo + -0.2514, -0.2766, 0.9275, + 0.0306, 0.9555, 0.2933, + 27.8571, -42.1305, -24.4563}, + {0.2765, -0.1121, -0.9545, % p_o3'_275_tfo + -0.8297, 0.4733, -0.2959, + 0.4850, 0.8737, 0.0379, + -14.7774, -45.2464, 21.9088}, + {0.1063, -0.6334, -0.7665, % p_o3'_180_tfo + -0.5932, -0.6591, 0.4624, + -0.7980, 0.4055, -0.4458, + 43.7634, 4.3296, 28.4890}, + {0.7136, -0.5032, -0.4873, % p_o3'_60_tfo + 0.6803, 0.3317, 0.6536, + -0.1673, -0.7979, 0.5791, + -17.1858, 41.4390, -27.0751}, + {21.3880, 15.0780, 45.5770}, % P + {21.9980, 14.5500, 46.8210}, % O1P + {21.1450, 14.0270, 44.5420}, % O2P + {22.1250, 16.3600, 44.9460}, % O5' + {23.5096, 16.1227, 44.5783}, % C5' + {23.5649, 15.8588, 43.5222}, % H5' + {23.9621, 15.4341, 45.2919}, % H5'' + {24.2805, 17.4138, 44.7151}, % C4' + {23.8509, 18.1819, 44.0720}, % H4' + {24.2506, 17.8583, 46.0741}, % O4' + {25.5830, 18.0320, 46.5775}, % C1' + {25.8569, 19.0761, 46.4256}, % H1' + {26.4410, 17.1555, 45.7033}, % C2' + {26.3459, 16.1253, 46.0462}, % H2'' + {27.7649, 17.5888, 45.6478}, % O2' + {28.1004, 17.9719, 46.4616}, % H2' + {25.7796, 17.2997, 44.3513}, % C3' + {25.9478, 16.3824, 43.7871}, % H3' + {26.2154, 18.4984, 43.6541}, % O3' + {25.7321, 17.6281, 47.9726}, % N1 + {25.5136, 18.5779, 48.9560}, % N3 + {25.2079, 19.7276, 48.6503}, % C2 + {25.6482, 18.1987, 50.2518}, % C4 + {25.9847, 16.9266, 50.6092}, % C5 + {26.0918, 16.6439, 51.8416}, % C6 + u, { + {26.2067, 15.9515, 49.5943}, % O2 + {26.0713, 16.3497, 48.3080}, % O4 + {25.4890, 18.9105, 51.0618}, % H3 + {26.4742, 14.9310, 49.8682}, % H5 + {26.2346, 15.6394, 47.4975}} % H6 + }. + +rUs() -> [rU01(),rU02(),rU03(),rU04(),rU05(),rU06(),rU07(), + rU08(),rU09(),rU10()]. + +rG_() -> + { + {-0.2067, -0.0264, 0.9780, % dgf_base_tfo + 0.9770, -0.0586, 0.2049, + 0.0519, 0.9979, 0.0379, + 1.0331, -46.8078, -36.4742}, + {-0.8644, -0.4956, -0.0851, % p_o3'_275_tfo + -0.0427, 0.2409, -0.9696, + 0.5010, -0.8345, -0.2294, + 4.0167, 54.5377, 12.4779}, + {0.3706, -0.6167, 0.6945, % p_o3'_180_tfo + -0.2867, -0.7872, -0.5460, + 0.8834, 0.0032, -0.4686, + -52.9020, 18.6313, -0.6709}, + {0.4155, 0.9025, -0.1137, % p_o3'_60_tfo + 0.9040, -0.4236, -0.0582, + -0.1007, -0.0786, -0.9918, + -7.6624, -25.2080, 49.5181}, + {31.3810, 0.1400, 47.5810}, % P + {29.9860, 0.6630, 47.6290}, % O1P + {31.7210, -0.6460, 48.8090}, % O2P + {32.4940, 1.2540, 47.2740}, % O5' + {32.1610, 2.2370, 46.2560}, % C5' + {31.2986, 2.8190, 46.5812}, % H5' + {32.0980, 1.7468, 45.2845}, % H5'' + {33.3476, 3.1959, 46.1947}, % C4' + {33.2668, 3.8958, 45.3630}, % H4' + {33.3799, 3.9183, 47.4216}, % O4' + {34.6515, 3.7222, 48.0398}, % C1' + {35.2947, 4.5412, 47.7180}, % H1' + {35.1756, 2.4228, 47.4827}, % C2' + {34.6778, 1.5937, 47.9856}, % H2'' + {36.5631, 2.2672, 47.4798}, % O2' + {37.0163, 2.6579, 48.2305}, % H2' + {34.6953, 2.5043, 46.0448}, % C3' + {34.5444, 1.4917, 45.6706}, % H3' + {35.6679, 3.3009, 45.3487}, % O3' + {37.4804, 4.0914, 52.2559}, % N1 + {36.9670, 4.1312, 49.9281}, % N3 + {37.8045, 4.2519, 50.9550}, % C2 + {35.7171, 3.8264, 50.3222}, % C4 + {35.2668, 3.6420, 51.6115}, % C5 + {36.2037, 3.7829, 52.6706}, % C6 + g, { + {39.0869, 4.5552, 50.7092}, % N2 + {33.9075, 3.3338, 51.6102}, % N7 + {34.6126, 3.6358, 49.5108}, % N9 + {33.5805, 3.3442, 50.3425}, % C8 + {35.9958, 3.6512, 53.8724}, % O6 + {38.2106, 4.2053, 52.9295}, % H1 + {39.8218, 4.6863, 51.3896}, % H21 + {39.3420, 4.6857, 49.7407}, % H22 + {32.5194, 3.1070, 50.2664}} % H8 + }. + +rU_() -> + { + {-0.0109, 0.5907, 0.8068, % dgf_base_tfo + 0.2217, -0.7853, 0.5780, + 0.9751, 0.1852, -0.1224, + -1.4225, -11.0956, -2.5217}, + {-0.8313, -0.4738, -0.2906, % p_o3'_275_tfo + 0.0649, 0.4366, -0.8973, + 0.5521, -0.7648, -0.3322, + 1.6833, 6.8060, -7.0011}, + {0.3445, -0.7630, 0.5470, % p_o3'_180_tfo + -0.4628, -0.6450, -0.6082, + 0.8168, -0.0436, -0.5753, + -6.8179, -3.9778, -5.9887}, + {0.5855, 0.7931, -0.1682, % p_o3'_60_tfo + 0.8103, -0.5790, 0.0906, + -0.0255, -0.1894, -0.9816, + 6.1203, -7.1051, 3.1984}, + {2.6760, -8.4960, 3.2880}, % P + {1.4950, -7.6230, 3.4770}, % O1P + {2.9490, -9.4640, 4.3740}, % O2P + {3.9730, -7.5950, 3.0340}, % O5' + {5.2430, -8.2420, 2.8260}, % C5' + {5.1974, -8.8497, 1.9223}, % H5' + {5.5548, -8.7348, 3.7469}, % H5'' + {6.3140, -7.2060, 2.5510}, % C4' + {5.8744, -6.2116, 2.4731}, % H4' + {7.2798, -7.2260, 3.6420}, % O4' + {8.5733, -6.9410, 3.1329}, % C1' + {8.9047, -6.0374, 3.6446}, % H1' + {8.4429, -6.6596, 1.6327}, % C2' + {9.2880, -7.1071, 1.1096}, % H2'' + {8.2502, -5.2799, 1.4754}, % O2' + {8.7676, -4.7284, 2.0667}, % H2' + {7.1642, -7.4416, 1.3021}, % C3' + {7.4125, -8.5002, 1.2260}, % H3' + {6.5160, -6.9772, 0.1267}, % O3' + {9.4531, -8.1107, 3.4087}, % N1 + {11.5931, -9.0015, 3.6357}, % N3 + {10.8101, -7.8950, 3.3748}, % C2 + {11.1439, -10.2744, 3.9206}, % C4 + {9.7056, -10.4026, 3.9332}, % C5 + {8.9192, -9.3419, 3.6833}, % C6 + u, { + {11.3013, -6.8063, 3.1326}, % O2 + {11.9431, -11.1876, 4.1375}, % O4 + {12.5840, -8.8673, 3.6158}, % H3 + {9.2891, -11.2898, 4.1313}, % H5 + {7.9263, -9.4537, 3.6977}} % H6 + }. + + +% -- PARTIAL INSTANTIATIONS -------------------------------------------------- + +%var ::= {Int, Tfo, Nuc} + +absolute_pos({_I,T,_N}, P) -> tfo_apply(T,P). + +atom_pos(Atom, {I,T,N}) -> + absolute_pos({I,T,N}, p_apply(Atom, N)). + +get_var(Id,[{Id,T,N}|_]) -> {Id,T,N}; +get_var(Id,[_|Lst]) -> get_var(Id,Lst). + +% make_relative_nuc(T, +% { +% Dgf_base_tfo,P_o3__275_tfo,P_o3__180_tfo,P_o3__60_tfo, +% P,O1p,O2p,O5_,C5_,H5_,H5__,C4_,H4_,O4_,C1_,H1_,C2_,H2__,O2_,H2_, +% C3_,H3_,O3_,N1,N3,C2,C4,C5,C6, +% a, {N6,N7,N9,C8,H2,H61,H62,H8} +% }) -> +% { +% Dgf_base_tfo, P_o3__275_tfo, P_o3__180_tfo, P_o3__60_tfo, +% tfo_apply(T, P), +% tfo_apply(T, O1p), +% tfo_apply(T, O2p), +% tfo_apply(T, O5_), +% tfo_apply(T, C5_), +% tfo_apply(T, H5_), +% tfo_apply(T, H5__), +% tfo_apply(T, C4_), +% tfo_apply(T, H4_), +% tfo_apply(T, O4_), +% tfo_apply(T, C1_), +% tfo_apply(T, H1_), +% tfo_apply(T, C2_), +% tfo_apply(T, H2__), +% tfo_apply(T, O2_), +% tfo_apply(T, H2_), +% tfo_apply(T, C3_), +% tfo_apply(T, H3_), +% tfo_apply(T, O3_), +% tfo_apply(T, N1), +% tfo_apply(T, N3), +% tfo_apply(T, C2), +% tfo_apply(T, C4), +% tfo_apply(T, C5), +% tfo_apply(T, C6), +% a, { +% tfo_apply(T, N6), +% tfo_apply(T, N7), +% tfo_apply(T, N9), +% tfo_apply(T, C8), +% tfo_apply(T, H2), +% tfo_apply(T, H61), +% tfo_apply(T, H62), +% tfo_apply(T, H8)} +% }; + +% make_relative_nuc(T, +% { +% Dgf_base_tfo,P_o3__275_tfo,P_o3__180_tfo,P_o3__60_tfo, +% P,O1p,O2p,O5_,C5_,H5_,H5__,C4_,H4_,O4_,C1_,H1_,C2_,H2__,O2_,H2_, +% C3_,H3_,O3_,N1,N3,C2,C4,C5,C6, +% c, {N4,O2,H41,H42,H5,H6} +% }) -> +% { +% Dgf_base_tfo, P_o3__275_tfo, P_o3__180_tfo, P_o3__60_tfo, +% tfo_apply(T, P), +% tfo_apply(T, O1p), +% tfo_apply(T, O2p), +% tfo_apply(T, O5_), +% tfo_apply(T, C5_), +% tfo_apply(T, H5_), +% tfo_apply(T, H5__), +% tfo_apply(T, C4_), +% tfo_apply(T, H4_), +% tfo_apply(T, O4_), +% tfo_apply(T, C1_), +% tfo_apply(T, H1_), +% tfo_apply(T, C2_), +% tfo_apply(T, H2__), +% tfo_apply(T, O2_), +% tfo_apply(T, H2_), +% tfo_apply(T, C3_), +% tfo_apply(T, H3_), +% tfo_apply(T, O3_), +% tfo_apply(T, N1), +% tfo_apply(T, N3), +% tfo_apply(T, C2), +% tfo_apply(T, C4), +% tfo_apply(T, C5), +% tfo_apply(T, C6), +% c, { +% tfo_apply(T, N4), +% tfo_apply(T, O2), +% tfo_apply(T, H41), +% tfo_apply(T, H42), +% tfo_apply(T, H5), +% tfo_apply(T, H6)} +% }; + +% make_relative_nuc(T, +% { +% Dgf_base_tfo,P_o3__275_tfo,P_o3__180_tfo,P_o3__60_tfo, +% P,O1p,O2p,O5_,C5_,H5_,H5__,C4_,H4_,O4_,C1_,H1_,C2_,H2__,O2_,H2_, +% C3_,H3_,O3_,N1,N3,C2,C4,C5,C6, +% g, {N2,N7,N9,C8,O6,H1,H21,H22,H8} +% }) -> +% { +% Dgf_base_tfo, P_o3__275_tfo, P_o3__180_tfo, P_o3__60_tfo, +% tfo_apply(T, P), +% tfo_apply(T, O1p), +% tfo_apply(T, O2p), +% tfo_apply(T, O5_), +% tfo_apply(T, C5_), +% tfo_apply(T, H5_), +% tfo_apply(T, H5__), +% tfo_apply(T, C4_), +% tfo_apply(T, H4_), +% tfo_apply(T, O4_), +% tfo_apply(T, C1_), +% tfo_apply(T, H1_), +% tfo_apply(T, C2_), +% tfo_apply(T, H2__), +% tfo_apply(T, O2_), +% tfo_apply(T, H2_), +% tfo_apply(T, C3_), +% tfo_apply(T, H3_), +% tfo_apply(T, O3_), +% tfo_apply(T, N1), +% tfo_apply(T, N3), +% tfo_apply(T, C2), +% tfo_apply(T, C4), +% tfo_apply(T, C5), +% tfo_apply(T, C6), +% g, { +% tfo_apply(T, N2), +% tfo_apply(T, N7), +% tfo_apply(T, N9), +% tfo_apply(T, C8), +% tfo_apply(T, O6), +% tfo_apply(T, H1), +% tfo_apply(T, H21), +% tfo_apply(T, H22), +% tfo_apply(T, H8)} +% }; + +% make_relative_nuc(T, +% { +% Dgf_base_tfo,P_o3__275_tfo,P_o3__180_tfo,P_o3__60_tfo, +% P,O1p,O2p,O5_,C5_,H5_,H5__,C4_,H4_,O4_,C1_,H1_,C2_,H2__,O2_,H2_, +% C3_,H3_,O3_,N1,N3,C2,C4,C5,C6, +% u, {O2,O4,H3,H5,H6} +% }) -> +% { +% Dgf_base_tfo, P_o3__275_tfo, P_o3__180_tfo, P_o3__60_tfo, +% tfo_apply(T, P), +% tfo_apply(T, O1p), +% tfo_apply(T, O2p), +% tfo_apply(T, O5_), +% tfo_apply(T, C5_), +% tfo_apply(T, H5_), +% tfo_apply(T, H5__), +% tfo_apply(T, C4_), +% tfo_apply(T, H4_), +% tfo_apply(T, O4_), +% tfo_apply(T, C1_), +% tfo_apply(T, H1_), +% tfo_apply(T, C2_), +% tfo_apply(T, H2__), +% tfo_apply(T, O2_), +% tfo_apply(T, H2_), +% tfo_apply(T, C3_), +% tfo_apply(T, H3_), +% tfo_apply(T, O3_), +% tfo_apply(T, N1), +% tfo_apply(T, N3), +% tfo_apply(T, C2), +% tfo_apply(T, C4), +% tfo_apply(T, C5), +% tfo_apply(T, C6), +% u, { +% tfo_apply(T, O2), +% tfo_apply(T, O4), +% tfo_apply(T, H3), +% tfo_apply(T, H5), +% tfo_apply(T, H6)} +% }. + +% -- SEARCH ------------------------------------------------------------------ + +% Sequential backtracking algorithm + +search(Partial_inst,[],_) -> + [Partial_inst]; +search(Partial_inst,[{F,Arg0,Arg1}|T],Constraint) -> + try_assignments(p_apply(F, Arg0,Arg1,Partial_inst), + Constraint, + Partial_inst, + T); +search(Partial_inst,[{F,Arg0,Arg1,Arg2}|T],Constraint) -> + try_assignments(p_apply(F, Arg0,Arg1,Arg2,Partial_inst), + Constraint, + Partial_inst, + T). + +try_assignments([],_,_,_) -> []; +try_assignments([V|Vs], Constraint, Partial_inst,T) -> + case p_apply(Constraint, V, Partial_inst) of + true -> append(search([V|Partial_inst],T,Constraint), + try_assignments(Vs, Constraint, Partial_inst,T)); + _ -> try_assignments(Vs, Constraint, Partial_inst,T) + end. + + +% -- DOMAINS ----------------------------------------------------------------- + +% Primary structure: strand A CUGCCACGUCUG, strand B CAGACGUGGCAG +% +% Secondary structure: strand A CUGCCACGUCUG +% |||||| +% GACGGUGCAGAC strand B +% +% Tertiary structure: +% +% 5' end of strand A C1----G12 3' end of strand B +% U2-------A11 +% G3-------C10 +% C4-----G9 +% C5---G8 +% A6 +% G6-C7 +% C5----G8 +% A4-------U9 +% G3--------C10 +% A2-------U11 +% 5' end of strand B C1----G12 3' end of strand A +% +% "helix", "stacked" and "connected" describe the spatial relationship +% between two consecutive nucleotides. E.g. the nucleotides C1 and U2 +% from the strand A. +% +% "wc" (stands for Watson-Crick and is a type of base-pairing), +% and "wc-dumas" describe the spatial relationship between +% nucleotides from two chains that are growing in opposite directions. +% E.g. the nucleotides C1 from strand A and G12 from strand B. + +% Dynamic Domains + +% Given, +% "ref" a nucleotide which is already positioned, +% "nuc" the nucleotide to be placed, +% and "tfo" a transformation matrix which expresses the desired +% relationship between "ref" and "nuc", +% the function "dgf-base" computes the transformation matrix that +% places the nucleotide "nuc" in the given relationship to "ref". + +dgf_base(Tfo, V, Nuc) -> + {_I,_T,N} = V, + tfo_combine(nuc_dgf_base_tfo(Nuc), + tfo_combine(Tfo,tfo_inv_ortho(process_type(type(N),V)))). + +process_type(a,V) -> + tfo_align(atom_pos(nuc_C1_, V),atom_pos(rA_N9, V),atom_pos(nuc_C4, V)); +process_type(c,V) -> + tfo_align(atom_pos(nuc_C1_, V),atom_pos(nuc_N1, V),atom_pos(nuc_C2, V)); +process_type(g,V) -> + tfo_align(atom_pos(nuc_C1_, V),atom_pos(rG_N9, V),atom_pos(nuc_C4, V)); +process_type(_,V) -> + tfo_align(atom_pos(nuc_C1_, V),atom_pos(nuc_N1, V),atom_pos(nuc_C2, V)). + + +% Placement of first nucleotide. + +reference(Nuc,I,_) -> + [{I,tfo_id(),Nuc}]. + +% The transformation matrix for wc is from: +% +% Chandrasekaran R. et al (1989) A Re-Examination of the Crystal +% Structure of A-DNA Using Fiber Diffraction Data. J. Biomol. +% Struct. & Dynamics 6(6):1189-1202. + +wc_tfo() -> + { + -1.0000, 0.0028, -0.0019, + 0.0028, 0.3468, -0.9379, + -0.0019, -0.9379, -0.3468, + -0.0080, 6.0730, 8.7208 + }. + +wc(Nuc,I,J,Partial_inst) -> + [{I,dgf_base(wc_tfo(),get_var(J,Partial_inst),Nuc),Nuc}]. + +wc_dumas_tfo() -> + { + -0.9737, -0.1834, 0.1352, + -0.1779, 0.2417, -0.9539, + 0.1422, -0.9529, -0.2679, + 0.4837, 6.2649, 8.0285 + }. + +wc_dumas(Nuc,I,J,Partial_inst) -> + [{I,dgf_base(wc_dumas_tfo(),get_var(J,Partial_inst),Nuc),Nuc}]. + +helix5__tfo() -> + { + 0.9886, -0.0961, 0.1156, + 0.1424, 0.8452, -0.5152, + -0.0482, 0.5258, 0.8492, + -3.8737, 0.5480, 3.8024 + }. + +helix5_(Nuc,I,J,Partial_inst) -> + [{I,dgf_base(helix5__tfo(),get_var(J,Partial_inst),Nuc),Nuc}]. + +helix3__tfo() -> + { + 0.9886, 0.1424, -0.0482, + -0.0961, 0.8452, 0.5258, + 0.1156, -0.5152, 0.8492, + 3.4426, 2.0474, -3.7042 + }. + +helix3_(Nuc,I,J,Partial_inst) -> + [{I,dgf_base(helix3__tfo(),get_var(J,Partial_inst),Nuc),Nuc}]. + +g37_a38_tfo() -> + { + 0.9991, 0.0164, -0.0387, + -0.0375, 0.7616, -0.6470, + 0.0189, 0.6478, 0.7615, + -3.3018, 0.9975, 2.5585 + }. + +g37_a38(Nuc,I,J,Partial_inst) -> + {I,dgf_base(g37_a38_tfo(),get_var(J,Partial_inst),Nuc),Nuc}. + +stacked5_(Nuc,I,J,Partial_inst) -> + [g37_a38(Nuc,I,J,Partial_inst) | helix5_(Nuc,I,J,Partial_inst)]. + +a38_g37_tfo() -> + { + 0.9991, -0.0375, 0.0189, + 0.0164, 0.7616, 0.6478, + -0.0387, -0.6470, 0.7615, + 3.3819, 0.7718, -2.5321 + }. + +a38_g37(Nuc,I,J,Partial_inst) -> + {I,dgf_base(a38_g37_tfo(),get_var(J,Partial_inst),Nuc),Nuc}. + +stacked3_(Nuc,I,J,Partial_inst) -> + [a38_g37(Nuc,I,J,Partial_inst) | helix3_(Nuc,I,J,Partial_inst)]. + +p_o3_(Nucs,I,J,Partial_inst) -> + generate([],Nucs,I,J,Partial_inst). + + +generate(Domains,[],_,_,_) -> + Domains; +generate(Domains,[N|Ns],I,J,Partial_inst) -> + Ref = get_var(J,Partial_inst), + Align = tfo_inv_ortho(tfo_align(atom_pos(nuc_O3_,Ref), + atom_pos(nuc_C3_,Ref), + atom_pos(nuc_C4_,Ref))), + generate([{I,tfo_combine(nuc_p_o3__60_tfo(N),Align),N}, + {I,tfo_combine(nuc_p_o3__180_tfo(N),Align),N}, + {I,tfo_combine(nuc_p_o3__275_tfo(N),Align),N} | Domains], + Ns,I,J,Partial_inst). + + +% -- PROBLEM STATEMENT ------------------------------------------------------- + +% Define anticodon problem -- Science 253:1255 Figure 3a, 3b and 3c + +% anticodon_domains() -> +% [ +% {reference, rC(), 27}, +% {helix5_, rC(), 28, 27}, +% {helix5_, rA(), 29, 28}, +% {helix5_, rG(), 30, 29}, +% {helix5_, rA(), 31, 30}, +% {wc, rU(), 39, 31}, +% {helix5_, rC(), 40, 39}, +% {helix5_, rU(), 41, 40}, +% {helix5_, rG(), 42, 41}, +% {helix5_, rG(), 43, 42}, +% {stacked3_, rA(), 38, 39}, +% {stacked3_, rG(), 37, 38}, +% {stacked3_, rA(), 36, 37}, +% {stacked3_, rA(), 35, 36}, +% {stacked3_, rG(), 34, 35}, %<-. Distance +% {p_o3_, rCs(), 32, 31}, % | Constraint +% {p_o3_, rUs(), 33, 32} %<-' 3.0 Angstroms +% ]. + +% Anticodon constraint + +anticodon_constraint({33,T,N},Partial_inst) -> + check0(dist(34,{33,T,N},Partial_inst)); +anticodon_constraint(_,_) -> true. + +check0(Dist) when is_float(Dist), Dist =< 3.0 -> true; +check0(_) -> false. + +dist(J,V,Partial_inst) -> + pt_dist(atom_pos(nuc_P, get_var(J,Partial_inst)), + atom_pos(nuc_O3_,V)). + +% anticodon() -> search([], anticodon_domains(), anticodon_constraint). + +% Define pseudoknot problem -- Science 253:1255 Figure 4a and 4b +pseudoknot_domains() -> + [ + {reference, rA(), 23}, + {wc_dumas, rU(), 8, 23}, + {helix3_, rG(), 22, 23}, + {wc_dumas, rC(), 9, 22}, + {helix3_, rG(), 21, 22}, + {wc_dumas, rC(), 10, 21}, + {helix3_, rC(), 20, 21}, + {wc_dumas, rG(), 11, 20}, + {helix3_, rU_(), 19, 20}, %<-. + {wc_dumas, rA(), 12, 19}, % | Distance +% % | Constraint +% Helix 1 % | 4.0 Angstroms + {helix3_, rC(), 3, 19}, % | + {wc_dumas, rG(), 13, 3}, % | + {helix3_, rC(), 2, 3}, % | + {wc_dumas, rG(), 14, 2}, % | + {helix3_, rC(), 1, 2}, % | + {wc_dumas, rG_(), 15, 1}, % | +% % | +% L2 LOOP % | + {p_o3_, rUs(), 16, 15}, % | + {p_o3_, rCs(), 17, 16}, % | + {p_o3_, rAs(), 18, 17}, %<-' +% +% L1 LOOP + {helix3_, rU(), 7, 8}, %<-. + {p_o3_, rCs(), 4, 3}, % | Constraint + {stacked5_, rU(), 5, 4}, % | 4.5 Angstroms + {stacked5_, rC(), 6, 5} %<-' + ]. + +% Pseudoknot constraint + +pseudoknot_constraint({18,T,N}, Partial_inst) -> + check1(dist(19, {18,T,N}, Partial_inst)); +pseudoknot_constraint({6,T,N}, Partial_inst) -> + check2(dist(7, {6,T,N}, Partial_inst)); +pseudoknot_constraint(_,_) -> true. + +check1(Dist) when is_float(Dist), Dist =< 4.0 -> true; +check1(_) -> false. + +check2(Dist) when is_float(Dist), Dist =< 4.5 -> true; +check2(_) -> false. + +pseudoknot() -> search([], pseudoknot_domains(), pseudoknot_constraint). + +% -- TESTING ----------------------------------------------------------------- + +list_of_atoms(N) -> + append(list_of_common_atoms(N),list_of_specific_atoms(N)). + +list_of_common_atoms + ({ + _,_,_,_, + P,O1p,O2p,O5_,C5_,H5_,H5__,C4_,H4_,O4_,C1_,H1_,C2_,H2__,O2_,H2_, + C3_,H3_,O3_,N1,N3,C2,C4,C5,C6, + _,_ + }) -> + [P,O1p,O2p,O5_,C5_,H5_,H5__,C4_,H4_,O4_,C1_,H1_,C2_,H2__,O2_,H2_, + C3_,H3_,O3_,N1,N3,C2,C4,C5,C6]. + +list_of_specific_atoms({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,a, + {N6,N7,N9,C8,H2,H61,H62,H8}}) -> + [N6,N7,N9,C8,H2,H61,H62,H8]; +list_of_specific_atoms({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,c, + {N4,O2,H41,H42,H5,H6}}) -> + [N4,O2,H41,H42,H5,H6]; +list_of_specific_atoms({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,g, + {N2,N7,N9,C8,O6,H1,H21,H22,H8}}) -> + [N2,N7,N9,C8,O6,H1,H21,H22,H8]; +list_of_specific_atoms({_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,_,u, + {O2,O4,H3,H5,H6}}) -> + [O2,O4,H3,H5,H6]. + +var_most_distant_atom(V) -> + {_,_,N} = V, + maximum(map(distance,V,list_of_atoms(N))). + +distance(V,P) -> + {X,Y,Z} = absolute_pos(V,P), + distance(X,Y,Z). + +distance(X,Y,Z) when is_float(X), is_float(Y), is_float(Z) -> + math:sqrt(X * X + Y * Y + Z * Z). + +sol_most_distant_atom(S) -> + maximum(map(var_most_distant_atom,S)). + +most_distant_atom(Sols) -> + maximum(map(sol_most_distant_atom, Sols)). + +maximum([H|T]) -> + max(T,H). + +max([H|T],M) when is_float(H), is_float(M), H > M -> + max(T,H); +max([_|T],M) -> + max(T,M); +max([],M) -> M. + +map(_Func,[]) -> []; +map(Func,[H|T]) -> + [p_apply(Func,H) | map(Func, T)]. + +map(_Func,_Arg,[]) -> []; +map(Func,Arg,[H|T]) -> + [p_apply(Func,Arg,H) | map(Func,Arg,T)]. + +% p_apply implements higher order functions +p_apply(sol_most_distant_atom, S) -> sol_most_distant_atom(S); +p_apply(var_most_distant_atom, V) -> var_most_distant_atom(V); +p_apply(nuc_C1_, X) -> nuc_C1_(X); +p_apply(nuc_C2, X) -> nuc_C2(X); +p_apply(nuc_C3_, X) -> nuc_C3_(X); +p_apply(nuc_C4, X) -> nuc_C4(X); +p_apply(nuc_C4_, X) -> nuc_C4_(X); +p_apply(nuc_N1, X) -> nuc_N1(X); +p_apply(nuc_O3_, X) -> nuc_O3_(X); +p_apply(nuc_P, X) -> nuc_P(X); +p_apply(nuc_dgf_base_tfo, X) -> nuc_dgf_base_tfo(X); +p_apply(nuc_p_o3__180_tfo, X) -> nuc_p_o3__180_tfo(X); +p_apply(nuc_p_o3__275_tfo, X) -> nuc_p_o3__275_tfo(X); +p_apply(nuc_p_o3__60_tfo, X) -> nuc_p_o3__60_tfo(X); +p_apply(rA_N9, X) -> rA_N9(X); +p_apply(rG_N9, X) -> rG_N9(X). + +p_apply(anticodon_constraint, V, P) -> anticodon_constraint(V, P); +p_apply(pseudoknot_constraint, V, P) -> pseudoknot_constraint(V, P); +p_apply(distance, V, P) -> distance(V, P). + +p_apply(reference, A1, A2, A3) -> reference(A1, A2, A3). + +p_apply(helix5_, A1, A2, A3, A4) -> helix5_(A1, A2, A3, A4); +p_apply(wc, A1, A2, A3, A4) -> wc(A1, A2, A3, A4); +p_apply(stacked3_, A1, A2, A3, A4) -> stacked3_(A1, A2, A3, A4); +p_apply(p_o3_, A1, A2, A3, A4) -> p_o3_(A1, A2, A3, A4); +p_apply(wc_dumas, A1, A2, A3, A4) -> wc_dumas(A1, A2, A3, A4); +p_apply(helix3_, A1, A2, A3, A4) -> helix3_(A1, A2, A3, A4); +p_apply(stacked5_, A1, A2, A3, A4) -> stacked5_(A1, A2, A3, A4). + +loop(0,R) -> R; +loop(N,_) -> loop(N-1,most_distant_atom(pseudoknot())). diff --git a/erts/emulator/test/random_iolist.erl b/erts/emulator/test/random_iolist.erl new file mode 100644 index 0000000000..4bce347d9a --- /dev/null +++ b/erts/emulator/test/random_iolist.erl @@ -0,0 +1,195 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%% Generate random iolists to be used by crypto_SUITE.erl +%% + +-module(random_iolist). + +-export([run/3, run2/3, standard_seed/0, compare/3, compare2/3, + random_iolist/1]). + +run(Iter,Fun1,Fun2) -> + standard_seed(), + compare(Iter,Fun1,Fun2). + +run2(Iter,Fun1,Fun2) -> + standard_seed(), + compare2(Iter,Fun1,Fun2). + +random_byte() -> + random:uniform(256) - 1. + +random_list(0,Acc) -> + Acc; +random_list(N,Acc) -> + random_list(N-1,[random_byte() | Acc]). + +random_binary(N) -> + B = list_to_binary(random_list(N,[])), + case {random:uniform(2),size(B)} of + {2,M} when M > 1 -> + S = M-1, + <<_:3,C:S/binary,_:5>> = B, + C; + _ -> + B + end. +random_list(N) -> + random_list(N,[]). + +front() -> + case random:uniform(10) of + 10 -> + false; + _ -> + true + end. + +any_type() -> + case random:uniform(10) of + 1 -> + list; + 2 -> + binary; + 3 -> + iolist; + _ -> + byte + end. + +tail_type() -> + case random:uniform(5) of + 1 -> + list; + 2 -> + iolist; + _ -> + binary + end. + +random_length(N) -> + UpperLimit = 255, + case N of + M when M > UpperLimit -> + random:uniform(UpperLimit+1) - 1; + _ -> + random:uniform(N+1) - 1 + end. + +random_iolist(0,Acc) -> + Acc; +random_iolist(N,Acc) -> + case front() of + true -> + case any_type() of + list -> + X = random_length(N), + L = random_list(X), + random_iolist(N-X,[L|Acc]); + binary -> + X = random_length(N), + B = random_binary(X), + random_iolist(N-X,[B|Acc]); + iolist -> + X = random_length(N), + B = random_iolist(X), + random_iolist(N-X,[B|Acc]); + byte -> + C = random_byte(), + random_iolist(N-1,[C|Acc]) + end; + false -> + case tail_type() of + list -> + X = random_length(N), + L = random_list(X), + random_iolist(N-X,[Acc|L]); + binary -> + X = random_length(N), + B = random_binary(X), + random_iolist(N-X,[Acc|B]); + iolist -> + X = random_length(N), + B = random_iolist(X), + random_iolist(N-X,[Acc|B]) + end + end. + +random_iolist(N) -> + random_iolist(N,[]). + + +standard_seed() -> + random:seed(1201,855653,380975). + +do_comp(List,F1,F2) -> + X = F1(List), + Y = F2(List), + case X =:= Y of + false -> + exit({not_matching,List,X,Y}); + _ -> + true + end. + +do_comp(List,List2,F1,F2) -> + X = F1(List,List2), + Y = F2(List,List2), + case X =:= Y of + false -> + exit({not_matching,List,List2,X,Y}); + _ -> + true + end. + +compare(0,Fun1,Fun2) -> + do_comp(<<>>,Fun1,Fun2), + do_comp([],Fun1,Fun2), + do_comp([[]|<<>>],Fun1,Fun2), + do_comp([<<>>,[]|<<>>],Fun1,Fun2), + true; + +compare(N,Fun1,Fun2) -> + L = random_iolist(N), + do_comp(L,Fun1,Fun2), + compare(N-1,Fun1,Fun2). + +compare2(0,Fun1,Fun2) -> + L = random_iolist(100), + do_comp(<<>>,L,Fun1,Fun2), + do_comp(L,<<>>,Fun1,Fun2), + do_comp(<<>>,<<>>,Fun1,Fun2), + do_comp([],L,Fun1,Fun2), + do_comp(L,[],Fun1,Fun2), + do_comp([],[],Fun1,Fun2), + do_comp([[]|<<>>],L,Fun1,Fun2), + do_comp(L,[[]|<<>>],Fun1,Fun2), + do_comp([[]|<<>>],[[]|<<>>],Fun1,Fun2), + do_comp([<<>>,[]|<<>>],L,Fun1,Fun2), + do_comp(L,[<<>>,[]|<<>>],Fun1,Fun2), + do_comp([<<>>,[]|<<>>],[<<>>,[]|<<>>],Fun1,Fun2), + true; + +compare2(N,Fun1,Fun2) -> + L = random_iolist(N), + L2 = random_iolist(N), + do_comp(L,L2,Fun1,Fun2), + compare2(N-1,Fun1,Fun2). diff --git a/erts/emulator/test/ref_SUITE.erl b/erts/emulator/test/ref_SUITE.erl new file mode 100644 index 0000000000..fa77095efd --- /dev/null +++ b/erts/emulator/test/ref_SUITE.erl @@ -0,0 +1,58 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(ref_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2]). +-export([wrap_1/1]). + +-export([loop_ref/1]). + +-include("test_server.hrl"). + +init_per_testcase(_, Config) -> + ?line Dog=test_server:timetrap(test_server:minutes(2)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_, Config) -> + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +all(suite) -> [wrap_1]. + +wrap_1(doc) -> "Check that refs don't wrap around easily."; +wrap_1(Config) when is_list(Config) -> + ?line spawn_link(?MODULE, loop_ref, [self()]), + ?line receive + done -> + test_server:fail(wrapfast) + after 30000 -> + ok + end, + ok. + +loop_ref(Parent) -> + Ref0 = make_ref(), + loop_ref(Ref0, first, 0), + Parent ! done. + +loop_ref(R, R, _) -> ok; +loop_ref(R0, _, N) -> + loop_ref(R0, make_ref(), N+1). diff --git a/erts/emulator/test/register_SUITE.erl b/erts/emulator/test/register_SUITE.erl new file mode 100644 index 0000000000..c03ee23b2e --- /dev/null +++ b/erts/emulator/test/register_SUITE.erl @@ -0,0 +1,87 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(register_SUITE). + + +%-define(line_trace, 1). + +-include("test_server.hrl"). + +%-compile(export_all). +-export([all/1, init_per_testcase/2, fin_per_testcase/2]). + +-export([otp_8099/1]). + +-define(DEFAULT_TIMEOUT, ?t:minutes(2)). + +all(doc) -> []; +all(suite) -> + [otp_8099]. + +init_per_testcase(Case, Config) when is_list(Config) -> + Dog = ?t:timetrap(?DEFAULT_TIMEOUT), + [{watchdog, Dog}, {testcase, Case} | Config]. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +%% +%% Test cases +%% + +-define(OTP_8099_NAME, otp_8099_reg_proc). + +otp_8099(Config) when is_list(Config) -> + case catch erlang:system_info(lock_counting) of + true -> {skipped, + "Lock counting enabled. Current lock counting " + "implementation cannot handle this many " + "processes."}; + _ -> + otp_8099_test(1000000) + end. + +otp_8099_test(0) -> + ok; +otp_8099_test(N) -> + ?line P = spawn(fun () -> otp_8099_proc() end), + ?line case catch register(?OTP_8099_NAME, P) of + true -> + ?line ok; + _ -> + ?line OP = whereis(?OTP_8099_NAME), + ?line (catch unregister(?OTP_8099_NAME)), + ?line (catch exit(OP, kill)), + ?line true = (catch register(?OTP_8099_NAME, P)) + end, + ?line P = whereis(?OTP_8099_NAME), + ?line exit(P, kill), + ?line otp_8099_test(N-1). + +otp_8099_proc() -> + receive _ -> ok end, + otp_8099_proc(). + +%% +%% Utils +%% + diff --git a/erts/emulator/test/save_calls_SUITE.erl b/erts/emulator/test/save_calls_SUITE.erl new file mode 100644 index 0000000000..b56c4ad0b0 --- /dev/null +++ b/erts/emulator/test/save_calls_SUITE.erl @@ -0,0 +1,256 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(save_calls_SUITE). + +-include("test_server.hrl"). + +-export([all/1]). + +-export([save_calls_1/1,dont_break_reductions/1]). + +-export([do_bopp/1, do_bipp/0, do_bepp/0]). + +all(suite) -> + [save_calls_1, dont_break_reductions]. + +dont_break_reductions(suite) -> + []; +dont_break_reductions(doc) -> + ["Check that save_calls dont break reduction-based scheduling"]; +dont_break_reductions(Config) when is_list(Config) -> + ?line RPS1 = reds_per_sched(0), + ?line RPS2 = reds_per_sched(20), + ?line Diff = abs(RPS1 - RPS2), + ?line true = (Diff < (0.05 * RPS1)), + ok. + + +reds_per_sched(SaveCalls) -> + ?line Parent = self(), + ?line HowMany = 10000, + ?line Pid = spawn(fun() -> + process_flag(save_calls,SaveCalls), + receive + go -> + carmichaels_below(HowMany), + Parent ! erlang:process_info(self(),reductions) + end + end), + ?line TH = spawn(fun() -> trace_handler(0,Parent,Pid) end), + ?line erlang:trace(Pid, true,[running,procs,{tracer,TH}]), + ?line Pid ! go, + ?line {Sched,Reds} = receive + {accumulated,X} -> + receive {reductions,Y} -> + {X,Y} + after 30000 -> + timeout + end + after 30000 -> + timeout + end, + ?line Reds div Sched. + + + +trace_handler(Acc,Parent,Client) -> + receive + {trace,Client,out,_} -> + trace_handler(Acc+1,Parent,Client); + {trace,Client,exit,_} -> + Parent ! {accumulated, Acc}; + _ -> + trace_handler(Acc,Parent,Client) + after 10000 -> + ok + end. + +save_calls_1(doc) -> "Test call saving."; +save_calls_1(Config) when is_list(Config) -> + case test_server:is_native(?MODULE) of + true -> {skipped,"Native code"}; + false -> save_calls_1() + end. + +save_calls_1() -> + ?line erlang:process_flag(self(), save_calls, 0), + ?line {last_calls, false} = process_info(self(), last_calls), + + ?line erlang:process_flag(self(), save_calls, 10), + ?line {last_calls, _L1} = process_info(self(), last_calls), + ?line ?MODULE:do_bipp(), + ?line {last_calls, L2} = process_info(self(), last_calls), + ?line L21 = lists:filter(fun is_local_function/1, L2), + ?line case L21 of + [{?MODULE,do_bipp,0}, + timeout, + 'send', + {?MODULE,do_bopp,1}, + 'receive', + timeout, + {?MODULE,do_bepp,0}] -> + ok; + X -> + test_server:fail({l21, X}) + end, + + ?line erlang:process_flag(self(), save_calls, 10), + ?line {last_calls, L3} = process_info(self(), last_calls), + ?line L31 = lists:filter(fun is_local_function/1, L3), + ?line [] = L31, + ok. + +do_bipp() -> + do_bopp(0), + do_bapp(), + ?MODULE:do_bopp(0), + do_bopp(3), + apply(?MODULE, do_bepp, []). + +do_bapp() -> + self() ! heffaklump. + +do_bopp(T) -> + receive + X -> X + after T -> ok + end. + +do_bepp() -> + ok. + +is_local_function({?MODULE, _, _}) -> + true; +is_local_function({_, _, _}) -> + false; +is_local_function(_) -> + true. + + +% Number crunching for reds test. +carmichaels_below(N) -> + random:seed(3172,9814,20125), + carmichaels_below(1,N). + +carmichaels_below(N,N2) when N >= N2 -> + 0; +carmichaels_below(N,N2) -> + X = case fast_prime(N,10) of + false -> 0; + true -> + case fast_prime2(N,10) of + true -> + %io:format("Prime: ~p~n",[N]), + 0; + false -> + io:format("Carmichael: ~p (dividable by ~p)~n", + [N,smallest_divisor(N)]), + 1 + end + end, + X+carmichaels_below(N+2,N2). + +expmod(_,E,_) when E == 0 -> + 1; +expmod(Base,Exp,Mod) when (Exp rem 2) == 0 -> + X = expmod(Base,Exp div 2,Mod), + (X*X) rem Mod; +expmod(Base,Exp,Mod) -> + (Base * expmod(Base,Exp - 1,Mod)) rem Mod. + +uniform(N) -> + random:uniform(N-1). + +fermat(N) -> + R = uniform(N), + expmod(R,N,N) == R. + +do_fast_prime(1,_) -> + true; +do_fast_prime(_N,0) -> + true; +do_fast_prime(N,Times) -> + case fermat(N) of + true -> + do_fast_prime(N,Times-1); + false -> + false + end. + +fast_prime(N,T) -> + do_fast_prime(N,T). + +expmod2(_,E,_) when E == 0 -> + 1; +expmod2(Base,Exp,Mod) when (Exp rem 2) == 0 -> +%% Uncomment the code below to simulate scheduling bug! +% case erlang:process_info(self(),last_calls) of +% {last_calls,false} -> ok; +% _ -> erlang:yield() +% end, + X = expmod2(Base,Exp div 2,Mod), + Y=(X*X) rem Mod, + if + Y == 1, X =/= 1, X =/= (Mod - 1) -> + 0; + true -> + Y rem Mod + end; +expmod2(Base,Exp,Mod) -> + (Base * expmod2(Base,Exp - 1,Mod)) rem Mod. + +miller_rabbin(N) -> + R = uniform(N), + expmod2(R,N,N) == R. + +do_fast_prime2(1,_) -> + true; +do_fast_prime2(_N,0) -> + true; +do_fast_prime2(N,Times) -> + case miller_rabbin(N) of + true -> + do_fast_prime2(N,Times-1); + false -> + false + end. + +fast_prime2(N,T) -> + do_fast_prime2(N,T). + +smallest_divisor(N) -> + find_divisor(N,2). + +find_divisor(N,TD) -> + if + TD*TD > N -> + N; + true -> + case divides(TD,N) of + true -> + TD; + false -> + find_divisor(N,TD+1) + end + end. + +divides(A,B) -> + (B rem A) == 0. + diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl new file mode 100644 index 0000000000..e644ad4dc8 --- /dev/null +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -0,0 +1,1378 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + + +%%%------------------------------------------------------------------- +%%% File : scheduler_SUITE.erl +%%% Author : Rickard Green +%%% Description : +%%% +%%% Created : 27 Oct 2008 by Rickard Green +%%%------------------------------------------------------------------- +-module(scheduler_SUITE). + + +%-define(line_trace, 1). + +-include("test_server.hrl"). + +%-compile(export_all). +-export([all/1, init_per_testcase/2, fin_per_testcase/2]). + +-export([equal/1, + few_low/1, + many_low/1, + equal_with_part_time_high/1, + equal_with_part_time_max/1, + equal_and_high_with_part_time_max/1, + equal_with_high/1, + equal_with_high_max/1, + bound_process/1, + scheduler_bind/1, + scheduler_bind_types/1, + cpu_topology/1, + sct_cmd/1, + sbt_cmd/1]). + +-define(DEFAULT_TIMEOUT, ?t:minutes(10)). + +-define(MIN_SCHEDULER_TEST_TIMEOUT, ?t:minutes(1)). + +all(doc) -> []; +all(suite) -> + [equal, + few_low, + many_low, + equal_with_part_time_high, + equal_with_part_time_max, + equal_and_high_with_part_time_max, + equal_with_high, + equal_with_high_max, + bound_process, + scheduler_bind]. + +init_per_testcase(Case, Config) when is_list(Config) -> + Dog = ?t:timetrap(?DEFAULT_TIMEOUT), + process_flag(priority, max), + erlang:display({'------------', ?MODULE, Case, '------------'}), + OkRes = ok, + [{watchdog, Dog}, {testcase, Case}, {ok_res, OkRes} |Config]. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +-define(ERTS_RUNQ_CHECK_BALANCE_REDS_PER_SCHED, (2000*2000)). +-define(DEFAULT_TEST_REDS_PER_SCHED, 200000000). + +%% +%% Test cases +%% + +equal(Config) when is_list(Config) -> + low_normal_test(Config, 500, 500). + +few_low(Config) when is_list(Config) -> + low_normal_test(Config, 1000, 2*active_schedulers()). + +many_low(Config) when is_list(Config) -> + low_normal_test(Config, 2*active_schedulers(), 1000). + +low_normal_test(Config, NW, LW) -> + ?line Tracer = start_tracer(), + ?line Low = workers(LW, low), + ?line Normal = workers(NW, normal), + ?line Res = do_it(Tracer, Low, Normal, [], []), + ?line chk_result(Res, LW, NW, 0, 0, true, false, false), + ?line workers_exit([Low, Normal]), + ?line ok(Res, Config). + +equal_with_part_time_high(Config) when is_list(Config) -> + ?line NW = 500, + ?line LW = 500, + ?line HW = 1, + ?line Tracer = start_tracer(), + ?line Normal = workers(NW, normal), + ?line Low = workers(LW, low), + ?line High = part_time_workers(HW, high), + ?line Res = do_it(Tracer, Low, Normal, High, []), + ?line chk_result(Res, LW, NW, HW, 0, true, true, false), + ?line workers_exit([Low, Normal, High]), + ?line ok(Res, Config). + +equal_and_high_with_part_time_max(Config) when is_list(Config) -> + ?line NW = 500, + ?line LW = 500, + ?line HW = 500, + ?line MW = 1, + ?line Tracer = start_tracer(), + ?line Low = workers(LW, low), + ?line Normal = workers(NW, normal), + ?line High = workers(HW, high), + ?line Max = part_time_workers(MW, max), + ?line Res = do_it(Tracer, Low, Normal, High, Max), + ?line chk_result(Res, LW, NW, HW, MW, false, true, true), + ?line workers_exit([Low, Normal, Max]), + ?line ok(Res, Config). + +equal_with_part_time_max(Config) when is_list(Config) -> + ?line NW = 500, + ?line LW = 500, + ?line MW = 1, + ?line Tracer = start_tracer(), + ?line Low = workers(LW, low), + ?line Normal = workers(NW, normal), + ?line Max = part_time_workers(MW, max), + ?line Res = do_it(Tracer, Low, Normal, [], Max), + ?line chk_result(Res, LW, NW, 0, MW, true, false, true), + ?line workers_exit([Low, Normal, Max]), + ?line ok(Res, Config). + +equal_with_high(Config) when is_list(Config) -> + ?line NW = 500, + ?line LW = 500, + ?line HW = 1, + ?line Tracer = start_tracer(), + ?line Low = workers(LW, low), + ?line Normal = workers(NW, normal), + ?line High = workers(HW, high), + ?line Res = do_it(Tracer, Low, Normal, High, []), + ?line LNExe = case active_schedulers() of + S when S =< HW -> false; + _ -> true + end, + ?line chk_result(Res, LW, NW, HW, 0, LNExe, true, false), + ?line workers_exit([Low, Normal, High]), + ?line ok(Res, Config). + +equal_with_high_max(Config) when is_list(Config) -> + ?line NW = 500, + ?line LW = 500, + ?line HW = 1, + ?line MW = 1, + ?line Tracer = start_tracer(), + ?line Normal = workers(NW, normal), + ?line Low = workers(LW, low), + ?line High = workers(HW, high), + ?line Max = workers(MW, max), + ?line Res = do_it(Tracer, Low, Normal, High, Max), + ?line {LNExe, HExe} = case active_schedulers() of + S when S =< MW -> {false, false}; + S when S =< (MW + HW) -> {false, true}; + _ -> {true, true} + end, + ?line chk_result(Res, LW, NW, HW, MW, LNExe, HExe, true), + ?line workers_exit([Low, Normal, Max]), + ?line ok(Res, Config). + +bound_process(Config) when is_list(Config) -> + case erlang:system_info(run_queues) == erlang:system_info(schedulers) of + true -> + ?line NStartBase = 20000, + ?line NStart = case {erlang:system_info(debug_compiled), + erlang:system_info(lock_checking)} of + {true, true} -> NStartBase div 100; + {_, true} -> NStartBase div 10; + _ -> NStartBase + end, + ?line MStart = 100, + ?line Seq = lists:seq(1, 100), + ?line Tester = self(), + ?line Procs = lists:map( + fun (N) when N rem 2 == 0 -> + spawn_opt(fun () -> + bound_loop(NStart, + NStart, + MStart, + 1), + Tester ! {self(), done} + end, + [{scheduler, 1}, link]); + (_N) -> + spawn_link(fun () -> + bound_loop(NStart, + NStart, + MStart, + false), + Tester ! {self(), done} + end) + end, + Seq), + ?line lists:foreach(fun (P) -> receive {P, done} -> ok end end, + Procs), + ?line ok; + false -> + {skipped, "Functionality not supported"} + end. + +bound_loop(_, 0, 0, _) -> + ok; +bound_loop(NS, 0, M, false) -> + bound_loop(NS, NS, M-1, false); +bound_loop(NS, N, M, false) -> + erlang:system_info(scheduler_id), + bound_loop(NS, N-1, M, false); +bound_loop(NS, 0, M, Sched) -> + NewSched = (Sched rem erlang:system_info(schedulers_online)) + 1, + Sched = process_flag(scheduler, NewSched), + NewSched = erlang:system_info(scheduler_id), + bound_loop(NS, NS, M-1, NewSched); +bound_loop(NS, N, M, Sched) -> + Sched = erlang:system_info(scheduler_id), + bound_loop(NS, N-1, M, Sched). + +scheduler_bind(suite) -> + [scheduler_bind_types, + cpu_topology, + sct_cmd, + sbt_cmd]. + +-define(TOPOLOGY_A_CMD, + "+sct" + "L0-1t0-1c0p0n0" + ":L2-3t0-1c1p0n0" + ":L4-5t0-1c0p1n0" + ":L6-7t0-1c1p1n0" + ":L8-9t0-1c0p2n1" + ":L10-11t0-1c1p2n1" + ":L12-13t0-1c0p3n1" + ":L14-15t0-1c1p3n1"). + +-define(TOPOLOGY_A_TERM, + [{node,[{processor,[{core,[{thread,{logical,0}}, + {thread,{logical,1}}]}, + {core,[{thread,{logical,2}}, + {thread,{logical,3}}]}]}, + {processor,[{core,[{thread,{logical,4}}, + {thread,{logical,5}}]}, + {core,[{thread,{logical,6}}, + {thread,{logical,7}}]}]}]}, + {node,[{processor,[{core,[{thread,{logical,8}}, + {thread,{logical,9}}]}, + {core,[{thread,{logical,10}}, + {thread,{logical,11}}]}]}, + {processor,[{core,[{thread,{logical,12}}, + {thread,{logical,13}}]}, + {core,[{thread,{logical,14}}, + {thread,{logical,15}}]}]}]}]). + +-define(TOPOLOGY_B_CMD, + "+sct" + "L0-1t0-1c0n0p0" + ":L2-3t0-1c1n0p0" + ":L4-5t0-1c2n1p0" + ":L6-7t0-1c3n1p0" + ":L8-9t0-1c0n2p1" + ":L10-11t0-1c1n2p1" + ":L12-13t0-1c2n3p1" + ":L14-15t0-1c3n3p1"). + +-define(TOPOLOGY_B_TERM, + [{processor,[{node,[{core,[{thread,{logical,0}}, + {thread,{logical,1}}]}, + {core,[{thread,{logical,2}}, + {thread,{logical,3}}]}]}, + {node,[{core,[{thread,{logical,4}}, + {thread,{logical,5}}]}, + {core,[{thread,{logical,6}}, + {thread,{logical,7}}]}]}]}, + {processor,[{node,[{core,[{thread,{logical,8}}, + {thread,{logical,9}}]}, + {core,[{thread,{logical,10}}, + {thread,{logical,11}}]}]}, + {node,[{core,[{thread,{logical,12}}, + {thread,{logical,13}}]}, + {core,[{thread,{logical,14}}, + {thread,{logical,15}}]}]}]}]). + +-define(TOPOLOGY_C_TERM, + [{node,[{processor,[{core,[{thread,{logical,0}}, + {thread,{logical,1}}]}, + {core,[{thread,{logical,2}}, + {thread,{logical,3}}]}]}, + {processor,[{core,[{thread,{logical,4}}, + {thread,{logical,5}}]}, + {core,[{thread,{logical,6}}, + {thread,{logical,7}}]}]}]}, + {processor,[{node,[{core,[{thread,{logical,8}}, + {thread,{logical,9}}]}, + {core,[{thread,{logical,10}}, + {thread,{logical,11}}]}]}, + {node,[{core,[{thread,{logical,12}}, + {thread,{logical,13}}]}, + {core,[{thread,{logical,14}}, + {thread,{logical,15}}]}]}]}, + {node,[{processor,[{core,[{thread,{logical,16}}, + {thread,{logical,17}}]}, + {core,[{thread,{logical,18}}, + {thread,{logical,19}}]}]}, + {processor,[{core,[{thread,{logical,20}}, + {thread,{logical,21}}]}, + {core,[{thread,{logical,22}}, + {thread,{logical,23}}]}]}]}, + {processor,[{node,[{core,[{thread,{logical,24}}, + {thread,{logical,25}}]}, + {core,[{thread,{logical,26}}, + {thread,{logical,27}}]}]}, + {node,[{core,[{thread,{logical,28}}, + {thread,{logical,29}}]}, + {core,[{thread,{logical,30}}, + {thread,{logical,31}}]}]}]}]). + + +-define(TOPOLOGY_C_CMD, + "+sct" + "L0-1t0-1c0p0n0" + ":L2-3t0-1c1p0n0" + ":L4-5t0-1c0p1n0" + ":L6-7t0-1c1p1n0" + ":L8-9t0-1c0n1p2" + ":L10-11t0-1c1n1p2" + ":L12-13t0-1c2n2p2" + ":L14-15t0-1c3n2p2" + ":L16-17t0-1c0p3n3" + ":L18-19t0-1c1p3n3" + ":L20-21t0-1c0p4n3" + ":L22-23t0-1c1p4n3" + ":L24-25t0-1c0n4p5" + ":L26-27t0-1c1n4p5" + ":L28-29t0-1c2n5p5" + ":L30-31t0-1c3n5p5"). + +-define(TOPOLOGY_D_TERM, + [{processor,[{node,[{core,[{thread,{logical,0}}, + {thread,{logical,1}}]}, + {core,[{thread,{logical,2}}, + {thread,{logical,3}}]}]}, + {node,[{core,[{thread,{logical,4}}, + {thread,{logical,5}}]}, + {core,[{thread,{logical,6}}, + {thread,{logical,7}}]}]}]}, + {node,[{processor,[{core,[{thread,{logical,8}}, + {thread,{logical,9}}]}, + {core,[{thread,{logical,10}}, + {thread,{logical,11}}]}]}, + {processor,[{core,[{thread,{logical,12}}, + {thread,{logical,13}}]}, + {core,[{thread,{logical,14}}, + {thread,{logical,15}}]}]}]}, + {processor,[{node,[{core,[{thread,{logical,16}}, + {thread,{logical,17}}]}, + {core,[{thread,{logical,18}}, + {thread,{logical,19}}]}]}, + {node,[{core,[{thread,{logical,20}}, + {thread,{logical,21}}]}, + {core,[{thread,{logical,22}}, + {thread,{logical,23}}]}]}]}, + {node,[{processor,[{core,[{thread,{logical,24}}, + {thread,{logical,25}}]}, + {core,[{thread,{logical,26}}, + {thread,{logical,27}}]}]}, + {processor,[{core,[{thread,{logical,28}}, + {thread,{logical,29}}]}, + {core,[{thread,{logical,30}}, + {thread,{logical,31}}]}]}]}]). + +-define(TOPOLOGY_D_CMD, + "+sct" + "L0-1t0-1c0n0p0" + ":L2-3t0-1c1n0p0" + ":L4-5t0-1c2n1p0" + ":L6-7t0-1c3n1p0" + ":L8-9t0-1c0p1n2" + ":L10-11t0-1c1p1n2" + ":L12-13t0-1c0p2n2" + ":L14-15t0-1c1p2n2" + ":L16-17t0-1c0n3p3" + ":L18-19t0-1c1n3p3" + ":L20-21t0-1c2n4p3" + ":L22-23t0-1c3n4p3" + ":L24-25t0-1c0p4n5" + ":L26-27t0-1c1p4n5" + ":L28-29t0-1c0p5n5" + ":L30-31t0-1c1p5n5"). + +-define(TOPOLOGY_E_CMD, + "+sct" + "L0-1t0-1c0p0n0" + ":L2-3t0-1c1p0n0" + ":L4-5t0-1c2p0n0" + ":L6-7t0-1c3p0n0" + ":L8-9t0-1c0p1n1" + ":L10-11t0-1c1p1n1" + ":L12-13t0-1c2p1n1" + ":L14-15t0-1c3p1n1"). + +-define(TOPOLOGY_E_TERM, + [{node,[{processor,[{core,[{thread,{logical,0}}, + {thread,{logical,1}}]}, + {core,[{thread,{logical,2}}, + {thread,{logical,3}}]}, + {core,[{thread,{logical,4}}, + {thread,{logical,5}}]}, + {core,[{thread,{logical,6}}, + {thread,{logical,7}}]}]}]}, + {node,[{processor,[{core,[{thread,{logical,8}}, + {thread,{logical,9}}]}, + {core,[{thread,{logical,10}}, + {thread,{logical,11}}]}, + {core,[{thread,{logical,12}}, + {thread,{logical,13}}]}, + {core,[{thread,{logical,14}}, + {thread,{logical,15}}]}]}]}]). + +-define(TOPOLOGY_F_CMD, + "+sct" + "L0-1t0-1c0n0p0" + ":L2-3t0-1c1n0p0" + ":L4-5t0-1c2n0p0" + ":L6-7t0-1c3n0p0" + ":L8-9t0-1c4n1p0" + ":L10-11t0-1c5n1p0" + ":L12-13t0-1c6n1p0" + ":L14-15t0-1c7n1p0" + ":L16-17t0-1c8n2p0" + ":L18-19t0-1c9n2p0" + ":L20-21t0-1c10n2p0" + ":L22-23t0-1c11n2p0" + ":L24-25t0-1c12n3p0" + ":L26-27t0-1c13n3p0" + ":L28-29t0-1c14n3p0" + ":L30-31t0-1c15n3p0"). + +-define(TOPOLOGY_F_TERM, + [{processor,[{node,[{core,[{thread,{logical,0}}, + {thread,{logical,1}}]}, + {core,[{thread,{logical,2}}, + {thread,{logical,3}}]}, + {core,[{thread,{logical,4}}, + {thread,{logical,5}}]}, + {core,[{thread,{logical,6}}, + {thread,{logical,7}}]}]}, + {node,[{core,[{thread,{logical,8}}, + {thread,{logical,9}}]}, + {core,[{thread,{logical,10}}, + {thread,{logical,11}}]}, + {core,[{thread,{logical,12}}, + {thread,{logical,13}}]}, + {core,[{thread,{logical,14}}, + {thread,{logical,15}}]}]}, + {node,[{core,[{thread,{logical,16}}, + {thread,{logical,17}}]}, + {core,[{thread,{logical,18}}, + {thread,{logical,19}}]}, + {core,[{thread,{logical,20}}, + {thread,{logical,21}}]}, + {core,[{thread,{logical,22}}, + {thread,{logical,23}}]}]}, + {node,[{core,[{thread,{logical,24}}, + {thread,{logical,25}}]}, + {core,[{thread,{logical,26}}, + {thread,{logical,27}}]}, + {core,[{thread,{logical,28}}, + {thread,{logical,29}}]}, + {core,[{thread,{logical,30}}, + {thread,{logical,31}}]}]}]}]). + +bindings(Node, BindType) -> + Parent = self(), + Ref = make_ref(), + spawn_link(Node, + fun () -> + enable_internal_state(), + Res = (catch erts_debug:get_internal_state( + {fake_scheduler_bindings, BindType})), + Parent ! {Ref, Res} + end), + receive + {Ref, Res} -> + ?t:format("~p: ~p~n", [BindType, Res]), + Res + end. + +scheduler_bind_types(Config) when is_list(Config) -> + ?line OldRelFlags = clear_erl_rel_flags(), + try + scheduler_bind_types_test(Config, + ?TOPOLOGY_A_TERM, + ?TOPOLOGY_A_CMD, + a), + scheduler_bind_types_test(Config, + ?TOPOLOGY_B_TERM, + ?TOPOLOGY_B_CMD, + b), + scheduler_bind_types_test(Config, + ?TOPOLOGY_C_TERM, + ?TOPOLOGY_C_CMD, + c), + scheduler_bind_types_test(Config, + ?TOPOLOGY_D_TERM, + ?TOPOLOGY_D_CMD, + d), + scheduler_bind_types_test(Config, + ?TOPOLOGY_E_TERM, + ?TOPOLOGY_E_CMD, + e), + scheduler_bind_types_test(Config, + ?TOPOLOGY_F_TERM, + ?TOPOLOGY_F_CMD, + f) + after + restore_erl_rel_flags(OldRelFlags) + end, + ?line ok. + +scheduler_bind_types_test(Config, Topology, CmdLine, TermLetter) -> + ?line ?t:format("Testing (~p): ~p~n", [TermLetter, Topology]), + ?line {ok, Node0} = start_node(Config), + ?line _ = rpc:call(Node0, erlang, system_flag, [cpu_topology, Topology]), + ?line cmp(Topology, rpc:call(Node0, erlang, system_info, [cpu_topology])), + ?line check_bind_types(Node0, TermLetter), + ?line stop_node(Node0), + ?line {ok, Node1} = start_node(Config, CmdLine), + ?line cmp(Topology, rpc:call(Node1, erlang, system_info, [cpu_topology])), + ?line check_bind_types(Node1, TermLetter), + ?line stop_node(Node1). + +check_bind_types(Node, a) -> + ?line {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} + = bindings(Node, no_spread), + ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} + = bindings(Node, thread_spread), + ?line {0,4,8,12,2,6,10,14,1,5,9,13,3,7,11,15} + = bindings(Node, processor_spread), + ?line {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15} + = bindings(Node, spread), + ?line {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15} + = bindings(Node, no_node_thread_spread), + ?line {0,4,2,6,1,5,3,7,8,12,10,14,9,13,11,15} + = bindings(Node, no_node_processor_spread), + ?line {0,4,2,6,8,12,10,14,1,5,3,7,9,13,11,15} + = bindings(Node, thread_no_node_processor_spread), + ?line {0,4,2,6,8,12,10,14,1,5,3,7,9,13,11,15} + = bindings(Node, default_bind), + ?line ok; +check_bind_types(Node, b) -> + ?line {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} + = bindings(Node, no_spread), + ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} + = bindings(Node, thread_spread), + ?line {0,8,2,10,4,12,6,14,1,9,3,11,5,13,7,15} + = bindings(Node, processor_spread), + ?line {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15} + = bindings(Node, spread), + ?line {0,2,1,3,4,6,5,7,8,10,9,11,12,14,13,15} + = bindings(Node, no_node_thread_spread), + ?line {0,2,1,3,4,6,5,7,8,10,9,11,12,14,13,15} + = bindings(Node, no_node_processor_spread), + ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} + = bindings(Node, thread_no_node_processor_spread), + ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} + = bindings(Node, default_bind), + ?line ok; +check_bind_types(Node, c) -> + ?line {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, + 25,26,27,28,29,30,31} = bindings(Node, no_spread), + ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15, + 17,19,21,23,25,27,29,31} = bindings(Node, thread_spread), + ?line {0,4,8,16,20,24,2,6,10,18,22,26,12,28,14,30,1,5,9,17,21,25, + 3,7,11,19,23,27,13,29,15,31} = bindings(Node, processor_spread), + ?line {0,8,16,24,4,20,12,28,2,10,18,26,6,22,14,30,1,9,17,25,5,21,13,29,3,11, + 19,27,7,23,15,31} = bindings(Node, spread), + ?line {0,2,4,6,1,3,5,7,8,10,9,11,12,14,13,15,16,18,20,22,17,19,21,23,24,26, + 25,27,28,30,29,31} = bindings(Node, no_node_thread_spread), + ?line {0,4,2,6,1,5,3,7,8,10,9,11,12,14,13,15,16,20,18,22,17,21,19,23,24,26, + 25,27,28,30,29,31} = bindings(Node, no_node_processor_spread), + ?line {0,4,2,6,8,10,12,14,16,20,18,22,24,26,28,30,1,5,3,7,9,11,13,15,17,21, + 19,23,25,27,29,31} = bindings(Node, thread_no_node_processor_spread), + ?line {0,4,2,6,8,10,12,14,16,20,18,22,24,26,28,30,1,5,3,7,9,11,13,15,17,21, + 19,23,25,27,29,31} = bindings(Node, default_bind), + ?line ok; +check_bind_types(Node, d) -> + ?line {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, + 25,26,27,28,29,30,31} = bindings(Node, no_spread), + ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15, + 17,19,21,23,25,27,29,31} = bindings(Node, thread_spread), + ?line {0,8,12,16,24,28,2,10,14,18,26,30,4,20,6,22,1,9,13,17,25,29,3,11,15, + 19,27,31,5,21,7,23} = bindings(Node, processor_spread), + ?line {0,8,16,24,12,28,4,20,2,10,18,26,14,30,6,22,1,9,17,25,13,29,5,21,3,11, + 19,27,15,31,7,23} = bindings(Node, spread), + ?line {0,2,1,3,4,6,5,7,8,10,12,14,9,11,13,15,16,18,17,19,20,22,21,23,24,26, + 28,30,25,27,29,31} = bindings(Node, no_node_thread_spread), + ?line {0,2,1,3,4,6,5,7,8,12,10,14,9,13,11,15,16,18,17,19,20,22,21,23,24,28, + 26,30,25,29,27,31} = bindings(Node, no_node_processor_spread), + ?line {0,2,4,6,8,12,10,14,16,18,20,22,24,28,26,30,1,3,5,7,9,13,11,15,17,19, + 21,23,25,29,27,31} = bindings(Node, thread_no_node_processor_spread), + ?line {0,2,4,6,8,12,10,14,16,18,20,22,24,28,26,30,1,3,5,7,9,13,11,15,17,19, + 21,23,25,29,27,31} = bindings(Node, default_bind), + ?line ok; +check_bind_types(Node, e) -> + ?line {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} + = bindings(Node, no_spread), + ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} + = bindings(Node, thread_spread), + ?line {0,8,2,10,4,12,6,14,1,9,3,11,5,13,7,15} + = bindings(Node, processor_spread), + ?line {0,8,2,10,4,12,6,14,1,9,3,11,5,13,7,15} + = bindings(Node, spread), + ?line {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15} + = bindings(Node, no_node_thread_spread), + ?line {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15} + = bindings(Node, no_node_processor_spread), + ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} + = bindings(Node, thread_no_node_processor_spread), + ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} + = bindings(Node, default_bind), + ?line ok; +check_bind_types(Node, f) -> + ?line {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, + 25,26,27,28,29,30,31} = bindings(Node, no_spread), + ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15, + 17,19,21,23,25,27,29,31} = bindings(Node, thread_spread), + ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13, + 15,17,19,21,23,25,27,29,31} = bindings(Node, processor_spread), + ?line {0,8,16,24,2,10,18,26,4,12,20,28,6,14,22,30,1,9,17,25,3,11,19,27,5,13, + 21,29,7,15,23,31} = bindings(Node, spread), + ?line {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15,16,18,20,22,17,19,21,23,24,26, + 28,30,25,27,29,31} = bindings(Node, no_node_thread_spread), + ?line {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15,16,18,20,22,17,19,21,23,24,26, + 28,30,25,27,29,31} = bindings(Node, no_node_processor_spread), + ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15,17,19, + 21,23,25,27,29,31} = bindings(Node, thread_no_node_processor_spread), + ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15,17,19, + 21,23,25,27,29,31} = bindings(Node, default_bind), + ?line ok; +check_bind_types(Node, _) -> + ?line bindings(Node, no_spread), + ?line bindings(Node, thread_spread), + ?line bindings(Node, processor_spread), + ?line bindings(Node, spread), + ?line bindings(Node, no_node_thread_spread), + ?line bindings(Node, no_node_processor_spread), + ?line bindings(Node, thread_no_node_processor_spread), + ?line bindings(Node, default_bind), + ?line ok. + +cpu_topology(Config) when is_list(Config) -> + ?line OldRelFlags = clear_erl_rel_flags(), + try + ?line cpu_topology_test( + Config, + [{node,[{processor,[{core,{logical,0}}, + {core,{logical,1}}]}]}, + {processor,[{node,[{core,{logical,2}}, + {core,{logical,3}}]}]}, + {node,[{processor,[{core,{logical,4}}, + {core,{logical,5}}]}]}, + {processor,[{node,[{core,{logical,6}}, + {core,{logical,7}}]}]}], + "+sct " + "L0-1c0-1p0n0" + ":L2-3c0-1n1p1" + ":L4-5c0-1p2n2" + ":L6-7c0-1n3p3"), + ?line cpu_topology_test( + Config, + [{node,[{processor,[{core,{logical,0}}, + {core,{logical,1}}]}, + {processor,[{core,{logical,2}}, + {core,{logical,3}}]}]}, + {processor,[{node,[{core,{logical,4}}, + {core,{logical,5}}]}, + {node,[{core,{logical,6}}, + {core,{logical,7}}]}]}, + {node,[{processor,[{core,{logical,8}}, + {core,{logical,9}}]}, + {processor,[{core,{logical,10}}, + {core,{logical,11}}]}]}, + {processor,[{node,[{core,{logical,12}}, + {core,{logical,13}}]}, + {node,[{core,{logical,14}}, + {core,{logical,15}}]}]}], + "+sct " + "L0-1c0-1p0n0" + ":L2-3c0-1p1n0" + ":L4-5c0-1n1p2" + ":L6-7c2-3n2p2" + ":L8-9c0-1p3n3" + ":L10-11c0-1p4n3" + ":L12-13c0-1n4p5" + ":L14-15c2-3n5p5"), + ?line cpu_topology_test( + Config, + [{node,[{processor,[{core,{logical,0}}, + {core,{logical,1}}]}]}, + {processor,[{node,[{core,{logical,2}}, + {core,{logical,3}}]}]}, + {processor,[{node,[{core,{logical,4}}, + {core,{logical,5}}]}]}, + {node,[{processor,[{core,{logical,6}}, + {core,{logical,7}}]}]}, + {node,[{processor,[{core,{logical,8}}, + {core,{logical,9}}]}]}, + {processor,[{node,[{core,{logical,10}}, + {core,{logical,11}}]}]}], + "+sct " + "L0-1c0-1p0n0" + ":L2-3c0-1n1p1" + ":L4-5c0-1n2p2" + ":L6-7c0-1p3n3" + ":L8-9c0-1p4n4" + ":L10-11c0-1n5p5") + after + restore_erl_rel_flags(OldRelFlags) + end, + ?line ok. + +cpu_topology_test(Config, Topology, Cmd) -> + ?line ?t:format("Testing~n ~p~n ~p~n", [Topology, Cmd]), + ?line cpu_topology_bif_test(Config, Topology), + ?line cpu_topology_cmdline_test(Config, Topology, Cmd), + ?line ok. + +cpu_topology_bif_test(_Config, false) -> + ?line ok; +cpu_topology_bif_test(Config, Topology) -> + ?line {ok, Node} = start_node(Config), + ?line _ = rpc:call(Node, erlang, system_flag, [cpu_topology, Topology]), + ?line cmp(Topology, rpc:call(Node, erlang, system_info, [cpu_topology])), + ?line stop_node(Node), + ?line ok. + +cpu_topology_cmdline_test(_Config, _Topology, false) -> + ?line ok; +cpu_topology_cmdline_test(Config, Topology, Cmd) -> + ?line {ok, Node} = start_node(Config, Cmd), + ?line cmp(Topology, rpc:call(Node, erlang, system_info, [cpu_topology])), + ?line stop_node(Node), + ?line ok. + +sct_cmd(Config) when is_list(Config) -> + ?line Topology = ?TOPOLOGY_A_TERM, + ?line OldRelFlags = clear_erl_rel_flags(), + try + ?line {ok, Node} = start_node(Config, ?TOPOLOGY_A_CMD), + ?line cmp(Topology, + rpc:call(Node, erlang, system_info, [cpu_topology])), + ?line cmp(Topology, + rpc:call(Node, erlang, system_flag, [cpu_topology, Topology])), + ?line cmp(Topology, + rpc:call(Node, erlang, system_info, [cpu_topology])), + ?line stop_node(Node) + after + restore_erl_rel_flags(OldRelFlags) + end, + ?line ok. + +-define(BIND_TYPES, + [{"u", unbound}, + {"ns", no_spread}, + {"ts", thread_spread}, + {"ps", processor_spread}, + {"s", spread}, + {"nnts", no_node_thread_spread}, + {"nnps", no_node_processor_spread}, + {"tnnps", thread_no_node_processor_spread}, + {"db", thread_no_node_processor_spread}]). + +sbt_cmd(Config) when is_list(Config) -> + Bind = try + OldVal = erlang:system_flag(scheduler_bind_type, default_bind), + erlang:system_flag(scheduler_bind_type, OldVal), + go_for_it + catch + error:notsup -> notsup; + error:_ -> go_for_it + end, + case Bind of + notsup -> + ?line {skipped, "Binding of schedulers not supported"}; + go_for_it -> + CpuTCmd = case erlang:system_info({cpu_topology,detected}) of + undefined -> + case os:type() of + linux -> + case erlang:system_info(logical_processors) of + 1 -> + "+sctL0"; + N when is_integer(N) -> + NS = integer_to_list(N-1), + "+sctL0-"++NS++"p0-"++NS; + _ -> + false + end; + _ -> + false + end; + _ -> + "" + end, + case CpuTCmd of + false -> + ?line {skipped, "Don't know how to create cpu topology"}; + _ -> + case erlang:system_info(logical_processors) of + LP when is_integer(LP) -> + OldRelFlags = clear_erl_rel_flags(), + try + lists:foreach(fun ({ClBt, Bt}) -> + ?line sbt_test(Config, + CpuTCmd, + ClBt, + Bt, + LP) + end, + ?BIND_TYPES) + after + restore_erl_rel_flags(OldRelFlags) + end, + ?line ok; + _ -> + ?line {skipped, + "Don't know the amount of logical processors"} + end + end + end. + +sbt_test(Config, CpuTCmd, ClBt, Bt, LP) -> + ?line ?t:format("Testing +sbt ~s (~p)~n", [ClBt, Bt]), + ?line LPS = integer_to_list(LP), + ?line Cmd = CpuTCmd++" +sbt "++ClBt++" +S"++LPS++":"++LPS, + ?line {ok, Node} = start_node(Config, Cmd), + ?line Bt = rpc:call(Node, + erlang, + system_info, + [scheduler_bind_type]), + ?line SB = rpc:call(Node, + erlang, + system_info, + [scheduler_bindings]), + ?line ?t:format("scheduler bindings: ~p~n", [SB]), + ?line BS = case {Bt, erlang:system_info(logical_processors_available)} of + {unbound, _} -> 0; + {_, Int} when is_integer(Int) -> Int; + {_, _} -> LP + end, + ?line lists:foldl(fun (S, 0) -> + ?line unbound = S, + 0; + (S, N) -> + ?line true = is_integer(S), + N-1 + end, + BS, + tuple_to_list(SB)), + ?line stop_node(Node), + ?line ok. + + +% +%% Utils +%% + +erl_rel_flag_var() -> + "ERL_"++erlang:system_info(otp_release)++"_FLAGS". + +clear_erl_rel_flags() -> + EnvVar = erl_rel_flag_var(), + case os:getenv(EnvVar) of + false -> + false; + Value -> + os:putenv(EnvVar, ""), + Value + end. + +restore_erl_rel_flags(false) -> + ok; +restore_erl_rel_flags(OldValue) -> + os:putenv(erl_rel_flag_var(), OldValue), + ok. + +ok(too_slow, _Config) -> + {comment, "Too slow system to do any actual testing..."}; +ok(_Res, Config) -> + ?config(ok_res, Config). + +chk_result(too_slow, + _LWorkers, + _NWorkers, + _HWorkers, + _MWorkers, + _LNShouldWork, + _HShouldWork, + _MShouldWork) -> + ?line ok; +chk_result([{low, L, Lmin, _Lmax}, + {normal, N, Nmin, _Nmax}, + {high, H, Hmin, _Hmax}, + {max, M, Mmin, _Mmax}] = Res, + LWorkers, + NWorkers, + HWorkers, + MWorkers, + LNShouldWork, + HShouldWork, + MShouldWork) -> + ?line ?t:format("~p~n", [Res]), + ?line Relax = relax_limits(), + case {L, N} of + {0, 0} -> + ?line false = LNShouldWork; + _ -> + ?line {LminRatioLim, + NminRatioLim, + LNRatioLimMin, + LNRatioLimMax} = case Relax of + false -> {0.5, 0.5, 0.05, 0.25}; + true -> {0.05, 0.05, 0.01, 0.4} + end, + ?line Lavg = L/LWorkers, + ?line Navg = N/NWorkers, + ?line Ratio = Lavg/Navg, + ?line LminRatio = Lmin/Lavg, + ?line NminRatio = Nmin/Navg, + ?line ?t:format("low min ratio=~p~n" + "normal min ratio=~p~n" + "low avg=~p~n" + "normal avg=~p~n" + "low/normal ratio=~p~n", + [LminRatio, NminRatio, Lavg, Navg, Ratio]), + erlang:display({low_min_ratio, LminRatio}), + erlang:display({normal_min_ratio, NminRatio}), + erlang:display({low_avg, Lavg}), + erlang:display({normal_avg, Navg}), + erlang:display({low_normal_ratio, Ratio}), + ?line chk_lim(LminRatioLim, LminRatio, 1.0, low_min_ratio), + ?line chk_lim(NminRatioLim, NminRatio, 1.0, normal_min_ratio), + ?line chk_lim(LNRatioLimMin, Ratio, LNRatioLimMax, low_normal_ratio), + ?line true = LNShouldWork, + ?line ok + end, + case H of + 0 -> + ?line false = HShouldWork; + _ -> + ?line HminRatioLim = case Relax of + false -> 0.5; + true -> 0.1 + end, + ?line Havg = H/HWorkers, + ?line HminRatio = Hmin/Havg, + erlang:display({high_min_ratio, HminRatio}), + ?line chk_lim(HminRatioLim, HminRatio, 1.0, high_min_ratio), + ?line true = HShouldWork, + ?line ok + end, + case M of + 0 -> + ?line false = MShouldWork; + _ -> + ?line MminRatioLim = case Relax of + false -> 0.5; + true -> 0.1 + end, + ?line Mavg = M/MWorkers, + ?line MminRatio = Mmin/Mavg, + erlang:display({max_min_ratio, MminRatio}), + ?line chk_lim(MminRatioLim, MminRatio, 1.0, max_min_ratio), + ?line true = MShouldWork, + ?line ok + end, + ?line ok. + + + +chk_lim(Min, V, Max, _What) when Min =< V, V =< Max -> + ok; +chk_lim(_Min, V, _Max, What) -> + ?t:fail({bad, What, V}). + +snd(_Msg, []) -> + []; +snd(Msg, [P|Ps]) -> + P ! Msg, + Ps. + +relax_limits() -> + case strange_system_scale() of + Scale when Scale > 1 -> + ?t:format("Relaxing limits~n", []), + true; + _ -> + false + end. + +strange_system_scale() -> + S0 = 1, + S1 = case erlang:system_info(schedulers_online) + > erlang:system_info(logical_processors) of + true -> S0*2; + false -> S0 + end, + S2 = case erlang:system_info(debug_compiled) of + true -> S1*10; + false -> + case erlang:system_info(lock_checking) of + true -> S1*2; + false -> S1 + end + end, + S3 = case lock_counting() of + true -> S2*2; + false -> S2 + end, + S3. + +lock_counting() -> + lock_counting(erlang:system_info(system_version)). + +lock_counting([]) -> + false; +lock_counting([$[,$l,$o,$c,$k,$-,$c,$o,$u,$n,$t,$i,$n,$g,$],_]) -> + true; +lock_counting([_C|Cs]) -> + lock_counting(Cs). + +go_work([], [], [], []) -> + []; +go_work(L, N, [], []) -> + go_work(snd(go_work, L), snd(go_work, N), [], []); +go_work(L, N, H, []) -> + go_work(L, N, snd(go_work, H), []); +go_work(L, N, H, M) -> + go_work(L, N, H, snd(go_work, M)). + +stop_work([], [], [], []) -> + []; +stop_work([], [], [], M) -> + stop_work([], [], [], snd(stop_work, M)); +stop_work([], [], H, M) -> + stop_work([], [], snd(stop_work, H), M); +stop_work(L, N, H, M) -> + stop_work(snd(stop_work, L), snd(stop_work, N), H, M). + +wait_balance(N) when is_integer(N) -> + case erlang:system_info(schedulers_active) of + 1 -> + done; + _ -> + erts_debug:set_internal_state(available_internal_state,true), + Start = erts_debug:get_internal_state(nbalance), + End = (Start + N) band ((1 bsl (8*erlang:system_info(wordsize)))-1), + wait_balance(Start, End), + erts_debug:set_internal_state(available_internal_state,false) + end. + +wait_balance(Start, End) -> + X = erts_debug:get_internal_state(nbalance), + case End =< X of + true -> + case Start =< End of + true -> + done; + false -> + case X < Start of + true -> + done; + false -> + receive after 250 -> ok end, + wait_balance(Start, End) + end + end; + false -> + receive after 250 -> ok end, + wait_balance(Start, End) + end. + +wait_reds(RedsLimit, Timeout) -> + Stop = erlang:start_timer(Timeout, self(), stop), + statistics(reductions), + wait_reds(0, RedsLimit, Stop). + +wait_reds(Reds, RedsLimit, Stop) when Reds < RedsLimit -> + receive + {timeout, Stop, stop} -> + erlang:display(timeout), + erlang:display({reduction_limit, RedsLimit}), + erlang:display({reductions, Reds}), + done + after 10000 -> + {_, NewReds} = statistics(reductions), + wait_reds(NewReds+Reds, RedsLimit, Stop) + end; +wait_reds(Reds, RedsLimit, Stop) when is_reference(Stop) -> + erlang:cancel_timer(Stop), + receive {timeout, Stop, stop} -> ok after 0 -> ok end, + wait_reds(Reds, RedsLimit, false); +wait_reds(Reds, RedsLimit, _Stop) -> + erlang:display({reduction_limit, RedsLimit}), + erlang:display({reductions, Reds}), + done. + +do_it(Tracer, Low, Normal, High, Max) -> + do_it(Tracer, Low, Normal, High, Max, ?DEFAULT_TEST_REDS_PER_SCHED). + +do_it(Tracer, Low, Normal, High, Max, RedsPerSchedLimit) -> + OldPrio = process_flag(priority, max), + go_work(Low, Normal, High, Max), + StartWait = now(), + %% Give the emulator a chance to balance the load... + wait_balance(5), + EndWait = now(), + BalanceWait = timer:now_diff(EndWait,StartWait) div 1000, + erlang:display({balance_wait, BalanceWait}), + Timeout = ?DEFAULT_TIMEOUT - ?t:seconds(10) - BalanceWait, + Res = case Timeout < ?MIN_SCHEDULER_TEST_TIMEOUT of + true -> + stop_work(Low, Normal, High, Max), + too_slow; + false -> + set_tracing(true, Tracer, normal, Normal), + set_tracing(true, Tracer, low, Low), + set_tracing(true, Tracer, high, High), + set_tracing(true, Tracer, max, Max), + wait_reds(RedsPerSchedLimit + * erlang:system_info(schedulers_online), + Timeout), + set_tracing(false, Tracer, normal, Normal), + set_tracing(false, Tracer, low, Low), + set_tracing(false, Tracer, high, High), + set_tracing(false, Tracer, max, Max), + stop_work(Low, Normal, High, Max), + get_trace_result(Tracer) + end, + process_flag(priority, OldPrio), + Res. + +workers_exit([]) -> + ok; +workers_exit([P|Ps]) when is_pid(P) -> + Mon = erlang:monitor(process, P), + unlink(P), + exit(P, kill), + workers_exit(Ps), + receive {'DOWN', Mon, process, P, _} -> ok end, + ok; +workers_exit([[]]) -> + ok; +workers_exit([Ps|Pss]) -> + workers_exit(Ps), + workers_exit(Pss). + +do_work(PartTime) -> + lists:reverse(lists:seq(1, 50)), + receive stop_work -> receive after infinity -> ok end after 0 -> ok end, + case PartTime of + true -> receive after 1 -> ok end; + false -> ok + end, + do_work(PartTime). + +workers(N, _Prio, _PartTime) when N =< 0 -> + []; +workers(N, Prio, PartTime) -> + Parent = self(), + W = spawn_opt(fun () -> + Parent ! {ready, self()}, + receive + go_work -> + do_work(PartTime) + end + end, + [{priority, Prio}, link]), + Ws = workers(N-1, Prio, PartTime), + receive {ready, W} -> ok end, + [W|Ws]. + +workers(N, Prio) -> + workers(N, Prio, false). + +part_time_workers(N, Prio) -> + workers(N, Prio, true). + +tracer(Low, Normal, High, Max) -> + receive + {tracees, Prio, Tracees} -> + save_tracees(Prio, Tracees), + case Prio of + low -> tracer(Tracees++Low, Normal, High, Max); + normal -> tracer(Low, Tracees++Normal, High, Max); + high -> tracer(Low, Normal, Tracees++High, Max); + max -> tracer(Low, Normal, High, Tracees++Max) + end; + {get_result, Ref, Who} -> + Delivered = erlang:trace_delivered(all), + receive + {trace_delivered, all, Delivered} -> + ok + end, + {Lc, Nc, Hc, Mc} = read_trace(), + GetMinMax + = fun (Prio, Procs) -> + LargeNum = 1 bsl 64, + case lists:foldl(fun (P, {Mn, Mx} = MnMx) -> + {Prio, C} = get(P), + case C < Mn of + true -> + case C > Mx of + true -> + {C, C}; + false -> + {C, Mx} + end; + false -> + case C > Mx of + true -> {Mn, C}; + false -> MnMx + end + end + end, + {LargeNum, 0}, + Procs) of + {LargeNum, 0} -> {0, 0}; + Res -> Res + end + end, + {Lmin, Lmax} = GetMinMax(low, Low), + {Nmin, Nmax} = GetMinMax(normal, Normal), + {Hmin, Hmax} = GetMinMax(high, High), + {Mmin, Mmax} = GetMinMax(max, Max), + Who ! {trace_result, Ref, [{low, Lc, Lmin, Lmax}, + {normal, Nc, Nmin, Nmax}, + {high, Hc, Hmin, Hmax}, + {max, Mc, Mmin, Mmax}]} + end. + +read_trace() -> + read_trace(0,0,0,0). + +read_trace(Low, Normal, High, Max) -> + receive + {trace, Proc, in, _} -> + {Prio, Count} = get(Proc), + put(Proc, {Prio, Count+1}), + case Prio of + low -> read_trace(Low+1, Normal, High, Max); + normal -> read_trace(Low, Normal+1, High, Max); + high -> read_trace(Low, Normal, High+1, Max); + max -> read_trace(Low, Normal, High, Max+1) + end; + {trace, _Proc, out, _} -> + read_trace(Low, Normal, High, Max) + after 0 -> + {Low, Normal, High, Max} + end. + +save_tracees(_Prio, []) -> + ok; +save_tracees(Prio, [T|Ts]) -> + put(T, {Prio, 0}), + save_tracees(Prio, Ts). + +start_tracer() -> + Tracer = spawn_link(fun () -> tracer([], [], [], []) end), + true = erlang:suspend_process(Tracer), + Tracer. + +get_trace_result(Tracer) -> + erlang:resume_process(Tracer), + Ref = make_ref(), + Tracer ! {get_result, Ref, self()}, + receive + {trace_result, Ref, Res} -> + Res + end. + + +set_tracing(_On, _Tracer, _Prio, []) -> + ok; +set_tracing(true, Tracer, Prio, Pids) -> + Tracer ! {tracees, Prio, Pids}, + set_tracing(true, Tracer, Pids); +set_tracing(false, Tracer, _Prio, Pids) -> + set_tracing(false, Tracer, Pids). + +set_tracing(_On, _Tracer, []) -> + ok; +set_tracing(On, Tracer, [Pid|Pids]) -> + 1 = erlang:trace(Pid, On, [running, {tracer, Tracer}]), + set_tracing(On, Tracer, Pids). + +active_schedulers() -> + case erlang:system_info(schedulers_online) of + 1 -> + 1; + N -> + case erlang:system_info(multi_scheduling) of + blocked -> 1; + enabled -> N + end + end. + +start_node(Config) -> + start_node(Config, ""). + +start_node(Config, Args) when is_list(Config) -> + ?line Pa = filename:dirname(code:which(?MODULE)), + ?line {A, B, C} = now(), + ?line Name = list_to_atom(atom_to_list(?MODULE) + ++ "-" + ++ atom_to_list(?config(testcase, Config)) + ++ "-" + ++ integer_to_list(A) + ++ "-" + ++ integer_to_list(B) + ++ "-" + ++ integer_to_list(C)), + ?line ?t:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]). + +stop_node(Node) -> + ?t:stop_node(Node). + + +enable_internal_state() -> + case catch erts_debug:get_internal_state(available_internal_state) of + true -> true; + _ -> erts_debug:set_internal_state(available_internal_state, true) + end. + +cmp(X, X) -> + ok; +cmp(X, Y) -> + ?t:format("cmp failed:~n X=~p~n Y=~p~n", [X,Y]), + cmp_aux(X, Y). + + +cmp_aux([X0|Y0], [X1|Y1]) -> + cmp_aux(X0, X1), + cmp_aux(Y0, Y1); +cmp_aux(T0, T1) when is_tuple(T0), is_tuple(T1), size(T0) == size(T1) -> + cmp_tuple(T0, T1, 1, size(T0)); +cmp_aux(X, X) -> + ok; +cmp_aux(F0, F1) -> + ?t:fail({no_match, F0, F1}). + +cmp_tuple(_T0, _T1, N, Sz) when N > Sz -> + ok; +cmp_tuple(T0, T1, N, Sz) -> + cmp_aux(element(N, T0), element(N, T1)), + cmp_tuple(T0, T1, N+1, Sz). diff --git a/erts/emulator/test/send_term_SUITE.erl b/erts/emulator/test/send_term_SUITE.erl new file mode 100644 index 0000000000..489adbd660 --- /dev/null +++ b/erts/emulator/test/send_term_SUITE.erl @@ -0,0 +1,354 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(send_term_SUITE). + +-export([all/1,basic/1]). +-export([init_per_testcase/2,fin_per_testcase/2]). + +-export([generate_external_terms_files/1]). + +-include("test_server.hrl"). + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog=?t:timetrap(?t:minutes(3)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +all(suite) -> + [basic]. + +basic(Config) when is_list(Config) -> + Drv = "send_term_drv", + ?line P = start_driver(Config, Drv), + + ?line [] = term(P, 0), + ?line Self = self(), + ?line {blurf,42,[],[-42,{}|"abc"++P],"kalle",3.1416,Self} = term(P, 1), + ?line Deep = lists:seq(0, 199), + ?line Deep = term(P, 2), + ?line {B1,B2} = term(P, 3), + ?line B1 = list_to_binary(lists:seq(0, 255)), + ?line B2 = list_to_binary(lists:seq(23, 255-17)), + + %% Pid sending. We need another process. + ?line Child = spawn_link(fun() -> + erlang:port_command(P, [4]) + end), + ?line {Self,Child} = receive_any(), + + %% ERL_DRV_EXT2TERM + ?line ExpectExt2Term = expected_ext2term_drv(?config(data_dir, Config)), + ?line ExpectExt2Term = term(P, 5), + + %% ERL_DRV_INT, ERL_DRV_UINT + ?line case erlang:system_info(wordsize) of + 4 -> + ?line {-1, 4294967295} = term(P, 6); + 8 -> + ?line {-1, 18446744073709551615} = term(P, 6) + end, + + %% ERL_DRV_BUF2BINARY + ?line ExpectedBinTup = {<<>>, + <<>>, + list_to_binary(lists:duplicate(17,17)), + list_to_binary(lists:duplicate(1024,17))}, + ?line ExpectedBinTup = term(P, 7), + + %% single terms + ?line [] = term(P, 8), % ERL_DRV_NIL + ?line '' = term(P, 9), % ERL_DRV_ATOM + ?line an_atom = term(P, 10), % ERL_DRV_ATOM + ?line -4711 = term(P, 11), % ERL_DRV_INT + ?line 4711 = term(P, 12), % ERL_DRV_UINT + ?line P = term(P, 13), % ERL_DRV_PORT + ?line <<>> = term(P, 14), % ERL_DRV_BINARY + ?line <<"hejsan">> = term(P, 15), % ERL_DRV_BINARY + ?line <<>> = term(P, 16), % ERL_DRV_BUF2BINARY + ?line <<>> = term(P, 17), % ERL_DRV_BUF2BINARY + ?line <<"hoppsan">> = term(P, 18), % ERL_DRV_BUF2BINARY + ?line "" = term(P, 19), % ERL_DRV_STRING + ?line "" = term(P, 20), % ERL_DRV_STRING + ?line "hippsan" = term(P, 21), % ERL_DRV_STRING + ?line {} = term(P, 22), % ERL_DRV_TUPLE + ?line [] = term(P, 23), % ERL_DRV_LIST + ?line Self = term(P, 24), % ERL_DRV_PID + ?line [] = term(P, 25), % ERL_DRV_STRING_CONS + ?line AFloat = term(P, 26), % ERL_DRV_FLOAT + ?line true = AFloat < 0.001, + ?line true = AFloat > -0.001, + ?line [] = term(P, 27), % ERL_DRV_EXT2TERM + ?line 18446744073709551615 = term(P, 28), % ERL_DRV_UINT64 + ?line 20233590931456 = term(P, 29), % ERL_DRV_UINT64 + ?line 4711 = term(P, 30), % ERL_DRV_UINT64 + ?line 0 = term(P, 31), % ERL_DRV_UINT64 + ?line 9223372036854775807 = term(P, 32), % ERL_DRV_INT64 + ?line 20233590931456 = term(P, 33), % ERL_DRV_INT64 + ?line 4711 = term(P, 34), % ERL_DRV_INT64 + ?line 0 = term(P, 35), % ERL_DRV_INT64 + ?line -1 = term(P, 36), % ERL_DRV_INT64 + ?line -4711 = term(P, 37), % ERL_DRV_INT64 + ?line -20233590931456 = term(P, 38), % ERL_DRV_INT64 + ?line -9223372036854775808 = term(P, 39), % ERL_DRV_INT64 + + %% Failure cases. + ?line [] = term(P, 127), + ?line receive + Any -> + ?line io:format("Unexpected: ~p\n", [Any]), + ?line ?t:fail() + after 0 -> + ok + end, + + ?line ok = chk_temp_alloc(), + + %% In a private heap system, verify that there are no binaries + %% left for the process. + ?line erlang:garbage_collect(), %Get rid of binaries. + case erlang:system_info(heap_type) of + private -> + ?line {binary,[]} = process_info(self(), binary); + _ -> ok + end, + + ?line stop_driver(P, Drv), + ok. + +term(P, Op) -> + erlang:port_command(P, [Op]), + receive_any(). + +receive_any() -> + receive + Any -> Any + end. + +chk_temp_alloc() -> + case erlang:system_info({allocator,temp_alloc}) of + false -> + %% Temp alloc is not enabled + ?line ok; + TIL -> + %% Verify that we havn't got anything allocated by temp_alloc + lists:foreach( + fun ({instance, _, TI}) -> + ?line {value, {mbcs, MBCInfo}} + = lists:keysearch(mbcs, 1, TI), + ?line {value, {blocks, 0, _, _}} + = lists:keysearch(blocks, 1, MBCInfo), + ?line {value, {sbcs, SBCInfo}} + = lists:keysearch(sbcs, 1, TI), + ?line {value, {blocks, 0, _, _}} + = lists:keysearch(blocks, 1, SBCInfo) + end, + TIL), + ?line ok + end. + + +%% Start/stop drivers. +start_driver(Config, Name) -> + Path = ?config(data_dir, Config), + erl_ddll:start(), + ok = load_driver(Path, Name), + open_port({spawn, Name}, []). + +load_driver(Dir, Driver) -> + case erl_ddll:load_driver(Dir, Driver) of + ok -> ok; + {error, Error} = Res -> + io:format("~s\n", [erl_ddll:format_error(Error)]), + Res + end. + +stop_driver(Port, Name) -> + ?line true = erlang:port_close(Port), + receive + {Port,Message} -> + ?t:fail({strange_message_from_port,Message}) + after 0 -> + ok + end, + + %% Unload the driver. + ok = erl_ddll:unload_driver(Name), + ?line ok = erl_ddll:stop(). + +get_external_terms(DataDir) -> + {ok, Bin} = file:read_file([DataDir, "ext_terms.bin"]), + binary_to_term(Bin). + +expected_ext2term_drv(DataDir) -> + make_expected_ext2term_drv(get_external_terms(DataDir)). + +make_expected_ext2term_drv([]) -> + []; +make_expected_ext2term_drv([T|Ts]) -> + [{T, T} | make_expected_ext2term_drv(Ts)]. + +%% +%% Generation of send_term_SUITE_data/ext_terms.h and +%% send_term_SUITE_data/ext_terms.bin +%% +%% These files should normally not need to be regenerated, +%% but we may want that if we introduce new types or make +%% backward incompatible changes to the external format. +%% + +generate_external_terms_files(BaseDir) -> + {ok,Node} = slave:start(hostname(), a_node), + RPid = rpc:call(Node, erlang, self, []), + true = is_pid(RPid), + RRef = rpc:call(Node, erlang, make_ref, []), + true = is_reference(RRef), + RPort = hd(rpc:call(Node, erlang, ports, [])), + true = is_port(RPort), + slave:stop(Node), + Terms = + [{4711, -4711, [an_atom, "a list"]}, + [1000000000000000000000,-1111111111111111, "blupp!", blipp], + {RPid, {RRef, RPort}, self(), hd(erlang:ports()), make_ref()}, + {{}, [], [], fun () -> ok end, <<"hej hopp trallalaaaaaaaaaaaaaaa">>}, + [44444444444444444444444,-44444444444, "b!", blippppppp], + {4711, RPid, {RRef, RPort}, -4711, [an_atom, "a list"]}, + {RPid, {RRef, RPort}, hd(processes()), hd(erlang:ports())}, + {4711, -4711, [an_atom, "a list"]}, + {4711, -4711, [atom, "list"]}, + {RPid, {RRef, RPort}, hd(processes()), hd(erlang:ports())}, + {4444444444444444444,-44444, {{{{{{{{{{{{}}}}}}}}}}}}, make_ref()}, + {444444444444444444444,-44444, [[[[[[[[[[[1]]]]]]]]]]], make_ref()}, + {444444444444444444,-44444, {{{{{{{{{{{{2}}}}}}}}}}}}, make_ref()}, + {4444444444444444444444,-44444, {{{{{{{{{{{{3}}}}}}}}}}}}, make_ref()}, + {44444444444444444444,-44444, {{{{{{{{{{{{4}}}}}}}}}}}}, make_ref()}, + {4444444444444444,-44444, [[[[[[[[[[[5]]]]]]]]]]], make_ref()}, + {444444444444444444444,-44444, {{{{{{{{{{{{6}}}}}}}}}}}}, make_ref()}, + {444444444444444,-44444, {{{{{{{{{{{{7}}}}}}}}}}}}, make_ref()}, + {4444444444444444444,-44444, {{{{{{{{{{{{8}}}}}}}}}}}}, make_ref()}], + ok = file:write_file(filename:join([BaseDir, + "send_term_SUITE_data", + "ext_terms.bin"]), + term_to_binary(Terms, [compressed])), + {ok, IoDev} = file:open(filename:join([BaseDir, + "send_term_SUITE_data", + "ext_terms.h"]), + [write]), + write_ext_terms_h(IoDev, Terms), + file:close(IoDev). + +write_ext_terms_h(IoDev, Terms) -> + write_license(IoDev), + io:format(IoDev, "#ifndef EXT_TERMS_H__~n",[]), + io:format(IoDev, "#define EXT_TERMS_H__~n",[]), + {ExtTerms, MaxSize} = make_ext_terms(Terms), + io:format(IoDev, + "static struct {~n" + " unsigned char ext[~p];~n" + " int ext_size;~n" + " unsigned char cext[~p];~n" + " int cext_size;~n" + "} ext_terms[] = {~n",[MaxSize, MaxSize]), + E = write_ext_terms_h(IoDev, ExtTerms, 0), + io:format(IoDev, "};~n",[]), + io:format(IoDev, "#define NO_OF_EXT_TERMS ~p~n", [E]), + io:format(IoDev, "#endif~n",[]). + +make_ext_terms([]) -> + {[], 0}; +make_ext_terms([T|Ts]) -> + E = term_to_binary(T), + ESz = size(E), + CE = term_to_binary(T, [compressed]), + CESz = size(CE), + true = CESz =< ESz, % Assertion + {ExtTerms, MaxSize} = make_ext_terms(Ts), + NewMaxSize = case MaxSize < ESz of + true -> ESz; + false -> MaxSize + end, + {[{E, ESz, CE, CESz} | ExtTerms], NewMaxSize}. + +write_ext_terms_h(IoDev, [], N) -> + io:format(IoDev, "~n",[]), + N; +write_ext_terms_h(IoDev, [ET|ETs], 0) -> + write_ext_term(IoDev, ET), + write_ext_terms_h(IoDev, ETs, 1); +write_ext_terms_h(IoDev, [ET|ETs], N) -> + io:format(IoDev, ",~n",[]), + write_ext_term(IoDev, ET), + write_ext_terms_h(IoDev, ETs, N+1). + +write_ext_term(IoDev, {E, ESz, CE, CESz}) -> + ESz = write_bytes(IoDev, " {{", binary_to_list(E), 0), + io:format(IoDev, + ",~n" + " ~p,~n", + [ESz]), + CESz = write_bytes(IoDev, " {", binary_to_list(CE), 0), + io:format(IoDev, + ",~n" + " ~p}", + [CESz]). + +write_bytes(IoDev, _, [], N) -> + io:format(IoDev, "}",[]), + N; +write_bytes(IoDev, Prefix, [B|Bs], N) -> + io:format(IoDev, "~s~w", [Prefix, B]), + write_bytes(IoDev, ",", Bs, N+1). + +write_license(IoDev) -> + S = "/* ``The contents of this file are subject to the Erlang Public License,~n" + " * Version 1.1, (the \"License\"); you may not use this file except in~n" + " * compliance with the License. You should have received a copy of the~n" + " * Erlang Public License along with this software. If not, it can be~n" + " * retrieved via the world wide web at http://www.erlang.org/.~n" + " * ~n" + " * Software distributed under the License is distributed on an \"AS IS\"~n" + " * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See~n" + " * the License for the specific language governing rights and limitations~n" + " * under the License.~n" + " * ~n" + " * The Initial Developer of the Original Code is Ericsson AB.~n" + " * Portions created by Ericsson are Copyright 2007, Ericsson AB.~n" + " * All Rights Reserved.''~n" + " * ~n" + " * $Id$~n" + " */~n" + "~n" + "/*~n" + " * Do not modify this file. This file and ext_terms.bin were~n" + " * automatically generated by send_term_SUITE:generate_external_terms_files/1~n" + " * and needs to be consistent with each other.~n" + " */~n", + io:format(IoDev, S, []). + + +hostname() -> + hostname(atom_to_list(node())). + +hostname([$@ | Hostname]) -> + list_to_atom(Hostname); +hostname([_C | Cs]) -> + hostname(Cs). diff --git a/erts/emulator/test/send_term_SUITE_data/Makefile.src b/erts/emulator/test/send_term_SUITE_data/Makefile.src new file mode 100644 index 0000000000..41a96ff626 --- /dev/null +++ b/erts/emulator/test/send_term_SUITE_data/Makefile.src @@ -0,0 +1,3 @@ +all: send_term_drv@dll@ + +@SHLIB_RULES@ diff --git a/erts/emulator/test/send_term_SUITE_data/ext_terms.bin b/erts/emulator/test/send_term_SUITE_data/ext_terms.bin Binary files differnew file mode 100644 index 0000000000..b239284323 --- /dev/null +++ b/erts/emulator/test/send_term_SUITE_data/ext_terms.bin diff --git a/erts/emulator/test/send_term_SUITE_data/ext_terms.h b/erts/emulator/test/send_term_SUITE_data/ext_terms.h new file mode 100644 index 0000000000..08134f3b05 --- /dev/null +++ b/erts/emulator/test/send_term_SUITE_data/ext_terms.h @@ -0,0 +1,110 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson AB. + * Portions created by Ericsson are Copyright 2007, Ericsson AB. + * All Rights Reserved.'' + * + * $Id$ + */ + +/* + * Do not modify this file. This file and ext_terms.bin were + * automatically generated by send_term_SUITE:generate_external_terms_files/1 + * and needs to be consistent with each other. + */ +#ifndef EXT_TERMS_H__ +#define EXT_TERMS_H__ +static struct { + unsigned char ext[162]; + int ext_size; + unsigned char cext[162]; + int cext_size; +} ext_terms[] = { + {{131,104,3,98,0,0,18,103,98,255,255,237,153,108,0,0,0,2,100,0,7,97,110,95,97,116,111,109,107,0,6,97,32,108,105,115,116,106}, + 38, + {131,104,3,98,0,0,18,103,98,255,255,237,153,108,0,0,0,2,100,0,7,97,110,95,97,116,111,109,107,0,6,97,32,108,105,115,116,106}, + 38}, + {{131,108,0,0,0,4,110,9,0,0,0,160,222,197,173,201,53,54,110,7,1,199,113,21,183,140,242,3,107,0,6,98,108,117,112,112,33,100,0,5,98,108,105,112,112,106}, + 46, + {131,108,0,0,0,4,110,9,0,0,0,160,222,197,173,201,53,54,110,7,1,199,113,21,183,140,242,3,107,0,6,98,108,117,112,112,33,100,0,5,98,108,105,112,112,106}, + 46}, + {{131,104,5,103,100,0,13,97,95,110,111,100,101,64,103,111,114,98,97,103,0,0,0,38,0,0,0,0,3,104,2,114,0,3,100,0,13,97,95,110,111,100,101,64,103,111,114,98,97,103,3,0,0,0,40,0,0,0,0,0,0,0,0,102,100,0,13,97,95,110,111,100,101,64,103,111,114,98,97,103,0,0,0,1,3,103,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,0,0,0,37,0,0,0,0,3,102,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,0,0,0,1,3,114,0,3,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,3,0,0,0,59,0,0,0,0,0,0,0,0}, + 162, + {131,80,0,0,0,161,120,156,203,96,77,79,97,224,77,140,207,203,79,73,117,72,207,47,74,74,76,103,96,96,80,3,98,6,230,12,166,34,6,102,116,89,102,160,140,6,3,20,164,97,209,203,200,12,52,145,39,17,85,80,21,108,96,26,166,4,35,51,216,14,20,97,144,21,214,48,43,0,1,209,36,52}, + 82}, + {{131,104,5,104,0,106,106,112,0,0,0,79,0,21,87,190,182,1,38,106,214,65,228,1,52,27,227,2,212,0,0,0,1,0,0,0,0,100,0,15,115,101,110,100,95,116,101,114,109,95,83,85,73,84,69,97,1,98,0,184,11,180,103,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,0,0,0,37,0,0,0,0,3,109,0,0,0,31,104,101,106,32,104,111,112,112,32,116,114,97,108,108,97,108,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97}, + 123, + {131,80,0,0,0,122,120,156,203,96,205,96,200,202,42,96,96,96,240,103,16,13,223,183,141,81,45,235,154,227,19,70,19,233,199,76,87,128,130,140,64,204,144,194,192,95,156,154,151,18,95,146,90,148,27,31,28,234,25,226,154,200,152,196,176,131,123,75,122,10,3,79,98,94,126,74,170,67,122,126,81,82,98,58,80,173,42,72,3,115,46,144,144,207,72,205,82,200,200,47,40,80,40,41,74,204,201,73,204,73,68,5,0,18,237,35,68}, + 117}, + {{131,108,0,0,0,4,110,10,0,28,199,113,166,118,185,145,86,105,9,110,5,1,28,103,24,89,10,107,0,2,98,33,100,0,10,98,108,105,112,112,112,112,112,112,112,106}, + 46, + {131,108,0,0,0,4,110,10,0,28,199,113,166,118,185,145,86,105,9,110,5,1,28,103,24,89,10,107,0,2,98,33,100,0,10,98,108,105,112,112,112,112,112,112,112,106}, + 46}, + {{131,104,5,98,0,0,18,103,103,100,0,13,97,95,110,111,100,101,64,103,111,114,98,97,103,0,0,0,38,0,0,0,0,3,104,2,114,0,3,100,0,13,97,95,110,111,100,101,64,103,111,114,98,97,103,3,0,0,0,40,0,0,0,0,0,0,0,0,102,100,0,13,97,95,110,111,100,101,64,103,111,114,98,97,103,0,0,0,1,3,98,255,255,237,153,108,0,0,0,2,100,0,7,97,110,95,97,116,111,109,107,0,6,97,32,108,105,115,116,106}, + 120, + {131,80,0,0,0,119,120,156,203,96,77,98,96,16,74,79,79,97,224,77,140,207,203,79,73,117,72,207,47,74,74,76,103,96,96,80,3,98,6,230,12,166,34,6,102,116,89,102,160,140,6,3,20,164,97,209,203,200,156,244,255,255,219,153,57,64,38,83,10,3,123,98,94,124,98,73,126,110,54,3,91,162,66,78,102,113,73,22,0,167,192,30,158}, + 93}, + {{131,104,4,103,100,0,13,97,95,110,111,100,101,64,103,111,114,98,97,103,0,0,0,38,0,0,0,0,3,104,2,114,0,3,100,0,13,97,95,110,111,100,101,64,103,111,114,98,97,103,3,0,0,0,40,0,0,0,0,0,0,0,0,102,100,0,13,97,95,110,111,100,101,64,103,111,114,98,97,103,0,0,0,1,3,103,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,0,0,0,0,0,0,0,0,3,102,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,0,0,0,1,3}, + 131, + {131,80,0,0,0,130,120,156,203,96,73,79,97,224,77,140,207,203,79,73,117,72,207,47,74,74,76,103,96,96,80,3,98,6,230,12,166,34,6,102,116,89,102,160,140,6,3,20,164,97,209,203,200,12,52,145,39,17,85,16,12,152,211,48,37,24,153,1,215,214,30,50}, + 72}, + {{131,104,3,98,0,0,18,103,98,255,255,237,153,108,0,0,0,2,100,0,7,97,110,95,97,116,111,109,107,0,6,97,32,108,105,115,116,106}, + 38, + {131,104,3,98,0,0,18,103,98,255,255,237,153,108,0,0,0,2,100,0,7,97,110,95,97,116,111,109,107,0,6,97,32,108,105,115,116,106}, + 38}, + {{131,104,3,98,0,0,18,103,98,255,255,237,153,108,0,0,0,2,100,0,4,97,116,111,109,107,0,4,108,105,115,116,106}, + 33, + {131,104,3,98,0,0,18,103,98,255,255,237,153,108,0,0,0,2,100,0,4,97,116,111,109,107,0,4,108,105,115,116,106}, + 33}, + {{131,104,4,103,100,0,13,97,95,110,111,100,101,64,103,111,114,98,97,103,0,0,0,38,0,0,0,0,3,104,2,114,0,3,100,0,13,97,95,110,111,100,101,64,103,111,114,98,97,103,3,0,0,0,40,0,0,0,0,0,0,0,0,102,100,0,13,97,95,110,111,100,101,64,103,111,114,98,97,103,0,0,0,1,3,103,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,0,0,0,0,0,0,0,0,3,102,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,0,0,0,1,3}, + 131, + {131,80,0,0,0,130,120,156,203,96,73,79,97,224,77,140,207,203,79,73,117,72,207,47,74,74,76,103,96,96,80,3,98,6,230,12,166,34,6,102,116,89,102,160,140,6,3,20,164,97,209,203,200,12,52,145,39,17,85,16,12,152,211,48,37,24,153,1,215,214,30,50}, + 72}, + {{131,104,4,110,8,0,28,199,17,175,172,214,173,61,98,255,255,82,100,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,0,114,0,3,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,3,0,0,0,60,0,0,0,0,0,0,0,0}, + 74, + {131,80,0,0,0,73,120,156,203,96,201,227,96,144,57,46,184,126,205,181,181,182,73,255,255,7,165,100,48,98,133,12,69,12,204,41,12,60,137,121,249,41,169,14,233,249,69,73,137,233,204,12,12,12,54,12,80,0,0,73,17,18,208}, + 63}, + {{131,104,4,110,9,0,28,199,241,98,116,219,231,23,24,98,255,255,82,100,108,0,0,0,1,108,0,0,0,1,108,0,0,0,1,108,0,0,0,1,108,0,0,0,1,108,0,0,0,1,108,0,0,0,1,108,0,0,0,1,108,0,0,0,1,108,0,0,0,1,107,0,1,1,106,106,106,106,106,106,106,106,106,106,114,0,3,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,3,0,0,0,61,0,0,0,0,0,0,0,0}, + 115, + {131,80,0,0,0,114,120,156,203,96,201,227,100,144,57,254,49,169,228,246,115,113,137,164,255,255,131,82,114,24,24,24,24,73,34,178,25,24,25,179,224,160,136,129,57,133,129,39,49,47,63,37,213,33,61,191,40,41,49,157,25,168,200,150,1,10,0,208,188,23,70}, + 71}, + {{131,104,4,110,8,0,28,199,129,17,222,251,42,6,98,255,255,82,100,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,97,2,114,0,3,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,3,0,0,0,62,0,0,0,0,0,0,0,0}, + 76, + {131,80,0,0,0,75,120,156,203,96,201,227,96,144,57,222,40,120,239,183,22,91,210,255,255,65,41,25,140,216,97,34,83,17,3,115,10,3,79,98,94,126,74,170,67,122,126,81,82,98,58,51,3,3,131,29,3,20,0,0,76,82,18,165}, + 64}, + {{131,104,4,110,9,0,28,199,113,221,139,146,14,239,240,98,255,255,82,100,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,97,3,114,0,3,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,3,0,0,0,63,0,0,0,0,0,0,0,0}, + 77, + {131,80,0,0,0,76,120,156,203,96,201,227,100,144,57,94,120,183,123,18,223,251,15,73,255,255,7,165,100,48,98,135,137,204,69,12,204,41,12,60,137,121,249,41,169,14,233,249,69,73,137,233,204,12,12,12,246,12,80,0,0,192,110,20,101}, + 65}, + {{131,104,4,110,9,0,28,199,177,214,190,98,202,104,2,98,255,255,82,100,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,97,4,114,0,3,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,3,0,0,0,64,0,0,0,0,0,0,0,0}, + 77, + {131,80,0,0,0,76,120,156,203,96,201,227,100,144,57,190,241,218,190,164,83,25,76,73,255,255,7,165,100,48,98,135,137,44,69,12,204,41,12,60,137,121,249,41,169,14,233,249,69,73,137,233,204,12,12,12,14,12,80,0,0,164,94,19,234}, + 65}, + {{131,104,4,110,7,0,28,199,85,220,50,202,15,98,255,255,82,100,108,0,0,0,1,108,0,0,0,1,108,0,0,0,1,108,0,0,0,1,108,0,0,0,1,108,0,0,0,1,108,0,0,0,1,108,0,0,0,1,108,0,0,0,1,108,0,0,0,1,107,0,1,5,106,106,106,106,106,106,106,106,106,106,114,0,3,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,3,0,0,0,65,0,0,0,0,0,0,0,0}, + 113, + {131,80,0,0,0,112,120,156,203,96,201,99,103,144,57,30,122,199,232,20,127,210,255,255,65,41,57,12,12,12,140,36,17,217,12,140,172,89,112,80,196,192,156,194,192,147,152,151,159,146,234,144,158,95,148,148,152,206,12,84,228,200,0,5,0,46,116,21,208}, + 69}, + {{131,104,4,110,9,0,28,199,241,98,116,219,231,23,24,98,255,255,82,100,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,97,6,114,0,3,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,3,0,0,0,66,0,0,0,0,0,0,0,0}, + 77, + {131,80,0,0,0,76,120,156,203,96,201,227,100,144,57,254,49,169,228,246,115,113,137,164,255,255,131,82,50,24,177,195,68,182,34,6,230,20,6,158,196,188,252,148,84,135,244,252,162,164,196,116,102,6,6,6,39,6,40,0,0,155,123,19,203}, + 65}, + {{131,104,4,110,7,0,28,199,59,73,56,148,1,98,255,255,82,100,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,97,7,114,0,3,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,3,0,0,0,67,0,0,0,0,0,0,0,0}, + 75, + {131,80,0,0,0,74,120,156,203,96,201,99,103,144,57,110,237,105,49,133,49,233,255,255,160,148,12,70,236,48,145,189,136,129,57,133,129,39,49,47,63,37,213,33,61,191,40,41,49,157,153,129,129,193,153,1,10,0,245,21,17,100}, + 62}, + {{131,104,4,110,8,0,28,199,17,175,172,214,173,61,98,255,255,82,100,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,104,1,97,8,114,0,3,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,3,0,0,0,68,0,0,0,0,0,0,0,0}, + 76, + {131,80,0,0,0,75,120,156,203,96,201,227,96,144,57,46,184,126,205,181,181,182,73,255,255,7,165,100,48,98,135,137,28,69,12,204,41,12,60,137,121,249,41,169,14,233,249,69,73,137,233,204,12,12,12,46,12,80,0,0,112,226,19,66}, + 64} +}; +#define NO_OF_EXT_TERMS 19 +#endif diff --git a/erts/emulator/test/send_term_SUITE_data/send_term_drv.c b/erts/emulator/test/send_term_SUITE_data/send_term_drv.c new file mode 100644 index 0000000000..6638de0560 --- /dev/null +++ b/erts/emulator/test/send_term_SUITE_data/send_term_drv.c @@ -0,0 +1,718 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "erl_driver.h" +#include <errno.h> +#include <string.h> + +static ErlDrvPort erlang_port; +static ErlDrvData send_term_drv_start(ErlDrvPort port, char *command); +static void send_term_drv_stop(ErlDrvData drv_data); +static void send_term_drv_run(ErlDrvData drv_data, char *buf, int len); + + +static int make_ext_term_list(ErlDrvTermData *td, int bad); + +#define FAIL_TERM(M, L) fail_term((M), (L), __LINE__) + +static ErlDrvEntry send_term_drv_entry = { + NULL, + send_term_drv_start, + send_term_drv_stop, + send_term_drv_run, + NULL, + NULL, + "send_term_drv", +}; + +DRIVER_INIT(send_term_drv) +{ + erlang_port = (ErlDrvPort)-1; + return &send_term_drv_entry; +} + +static ErlDrvData send_term_drv_start(ErlDrvPort port, char *buf) +{ + if (erlang_port != (ErlDrvPort)-1) { + return ERL_DRV_ERROR_GENERAL; + } + + erlang_port = port; + return (ErlDrvData)port; +} + +static void send_term_drv_stop(ErlDrvData drv_data) +{ +} + +static void output_term(ErlDrvTermData* msg, int len); +static void fail_term(ErlDrvTermData* msg, int len, int line); + +static void send_term_drv_run(ErlDrvData port, char *buf, int count) +{ + ErlDrvTermData msg[1024]; + + switch (*buf) { + case 0: + msg[0] = ERL_DRV_NIL; + output_term(msg, 1); + break; + + case 1: /* Most term types inside a tuple. */ + { + double f = 3.1416; + + msg[0] = ERL_DRV_ATOM; + msg[1] = driver_mk_atom("blurf"), + msg[2] = ERL_DRV_INT; + msg[3] = (ErlDrvTermData) 42; + msg[4] = ERL_DRV_NIL; + msg[5] = ERL_DRV_INT; + msg[6] = (ErlDrvTermData) -42; + msg[7] = ERL_DRV_TUPLE; + msg[8] = (ErlDrvTermData) 0; + msg[9] = ERL_DRV_PORT; + msg[10] = driver_mk_port(erlang_port); + msg[11] = ERL_DRV_STRING_CONS; + msg[12] = (ErlDrvTermData) "abc"; + msg[13] = (ErlDrvTermData) 3; + msg[14] = ERL_DRV_LIST; + msg[15] = (ErlDrvTermData) 3; + msg[16] = ERL_DRV_STRING; + msg[17] = (ErlDrvTermData) "kalle"; + msg[18] = (ErlDrvTermData) 5; + msg[19] = ERL_DRV_FLOAT; + msg[20] = (ErlDrvTermData) &f; + msg[21] = ERL_DRV_PID; + msg[22] = driver_connected(erlang_port); + msg[23] = ERL_DRV_TUPLE; + msg[24] = (ErlDrvTermData) 7; + output_term(msg, 25); + } + break; + + case 2: /* Deep stack */ + { + int i; + + for (i = 0; i < 400; i += 2) { + msg[i] = ERL_DRV_INT; + msg[i+1] = (ErlDrvTermData) (i / 2); + } + msg[i] = ERL_DRV_NIL; + msg[i+1] = ERL_DRV_LIST; + msg[i+2] = (ErlDrvTermData) 201; + output_term(msg, i+3); + } + break; + + case 3: /* Binaries */ + { + ErlDrvBinary* bin; + int i; + + bin = driver_alloc_binary(256); + for (i = 0; i < 256; i++) { + bin->orig_bytes[i] = i; + } + msg[0] = ERL_DRV_BINARY; + msg[1] = (ErlDrvTermData) bin; + msg[2] = (ErlDrvTermData) 256; + msg[3] = (ErlDrvTermData) 0; + msg[4] = ERL_DRV_BINARY; + msg[5] = (ErlDrvTermData) bin; + msg[6] = (ErlDrvTermData) 256-23-17; + msg[7] = (ErlDrvTermData) 23; + msg[8] = ERL_DRV_TUPLE; + msg[9] = (ErlDrvTermData) 2; + output_term(msg, 10); + driver_free_binary(bin); + } + break; + + case 4: /* Pids */ + msg[0] = ERL_DRV_PID; + msg[1] = driver_connected(erlang_port); + msg[2] = ERL_DRV_PID; + msg[3] = driver_caller(erlang_port); + msg[4] = ERL_DRV_TUPLE; + msg[5] = (ErlDrvTermData) 2; + output_term(msg, 6); + break; + + case 5: + output_term(msg, make_ext_term_list(msg, 0)); + break; + + case 6: + msg[0] = ERL_DRV_INT; + msg[1] = ~((ErlDrvTermData) 0); + msg[2] = ERL_DRV_UINT; + msg[3] = ~((ErlDrvTermData) 0); + msg[4] = ERL_DRV_TUPLE; + msg[5] = (ErlDrvTermData) 2; + output_term(msg, 6); + break; + + case 7: { + int len = 0; + char buf[1024]; + memset(buf, 17, sizeof(buf)); + /* empty heap binary */ + msg[len++] = ERL_DRV_BUF2BINARY; + msg[len++] = (ErlDrvTermData) NULL; /* NULL is ok if size == 0 */ + msg[len++] = (ErlDrvTermData) 0; + /* empty heap binary again */ + msg[len++] = ERL_DRV_BUF2BINARY; + msg[len++] = (ErlDrvTermData) &buf[0]; /* ptr is ok if size == 0 */ + msg[len++] = (ErlDrvTermData) 0; + /* heap binary */ + msg[len++] = ERL_DRV_BUF2BINARY; + msg[len++] = (ErlDrvTermData) &buf[0]; + msg[len++] = (ErlDrvTermData) 17; + /* off heap binary */ + msg[len++] = ERL_DRV_BUF2BINARY; + msg[len++] = (ErlDrvTermData) &buf[0]; + msg[len++] = (ErlDrvTermData) sizeof(buf); + + msg[len++] = ERL_DRV_TUPLE; + msg[len++] = (ErlDrvTermData) 4; + + output_term(msg, len); + break; + } + + case 8: + msg[0] = ERL_DRV_NIL; + output_term(msg, 1); + break; + + case 9: + msg[0] = ERL_DRV_ATOM; + msg[1] = (ErlDrvTermData) driver_mk_atom(""); + output_term(msg, 2); + break; + + case 10: + msg[0] = ERL_DRV_ATOM; + msg[1] = (ErlDrvTermData) driver_mk_atom("an_atom"); + output_term(msg, 2); + break; + + case 11: + msg[0] = ERL_DRV_INT; + msg[1] = (ErlDrvTermData) -4711; + output_term(msg, 2); + break; + + case 12: + msg[0] = ERL_DRV_UINT; + msg[1] = (ErlDrvTermData) 4711; + output_term(msg, 2); + + break; + case 13: + msg[0] = ERL_DRV_PORT; + msg[1] = driver_mk_port(erlang_port); + output_term(msg, 2); + break; + + case 14: { + ErlDrvBinary *dbin = driver_alloc_binary(0); + msg[0] = ERL_DRV_BINARY; + msg[1] = (ErlDrvTermData) dbin; + msg[2] = (ErlDrvTermData) 0; + msg[3] = (ErlDrvTermData) 0; + output_term(msg, 4); + driver_free_binary(dbin); + break; + } + + case 15: { + char buf[] = "hejsan"; + ErlDrvBinary *dbin = driver_alloc_binary(sizeof(buf)-1); + if (dbin) + memcpy((void *) dbin->orig_bytes, (void *) buf, sizeof(buf)-1); + msg[0] = ERL_DRV_BINARY; + msg[1] = (ErlDrvTermData) dbin; + msg[2] = (ErlDrvTermData) (dbin ? sizeof(buf)-1 : 0); + msg[3] = (ErlDrvTermData) 0; + output_term(msg, 4); + driver_free_binary(dbin); + break; + } + + case 16: + msg[0] = ERL_DRV_BUF2BINARY; + msg[1] = (ErlDrvTermData) NULL; + msg[2] = (ErlDrvTermData) 0; + output_term(msg, 3); + break; + + case 17: { + char buf[] = ""; + msg[0] = ERL_DRV_BUF2BINARY; + msg[1] = (ErlDrvTermData) buf; + msg[2] = (ErlDrvTermData) sizeof(buf)-1; + output_term(msg, 3); + break; + } + + case 18: { + char buf[] = "hoppsan"; + msg[0] = ERL_DRV_BUF2BINARY; + msg[1] = (ErlDrvTermData) buf; + msg[2] = (ErlDrvTermData) sizeof(buf)-1; + output_term(msg, 3); + break; + } + + case 19: + msg[0] = ERL_DRV_STRING; + msg[1] = (ErlDrvTermData) buf; + msg[2] = (ErlDrvTermData) 0; + output_term(msg, 3); + break; + + case 20: { + char buf[] = ""; + msg[0] = ERL_DRV_STRING; + msg[1] = (ErlDrvTermData) buf; + msg[2] = (ErlDrvTermData) sizeof(buf)-1; + output_term(msg, 3); + break; + } + + case 21: { + char buf[] = "hippsan"; + msg[0] = ERL_DRV_STRING; + msg[1] = (ErlDrvTermData) buf; + msg[2] = (ErlDrvTermData) sizeof(buf)-1; + output_term(msg, 3); + break; + } + + case 22: + msg[0] = ERL_DRV_TUPLE; + msg[1] = (ErlDrvTermData) 0; + output_term(msg, 2); + break; + + case 23: + msg[0] = ERL_DRV_NIL; + msg[1] = ERL_DRV_LIST; + msg[2] = (ErlDrvTermData) 1; + output_term(msg, 3); + break; + + case 24: + msg[0] = ERL_DRV_PID; + msg[1] = driver_connected(erlang_port); + output_term(msg, 2); + break; + + case 25: + msg[0] = ERL_DRV_NIL; + msg[1] = ERL_DRV_STRING_CONS; + msg[2] = (ErlDrvTermData) ""; + msg[3] = (ErlDrvTermData) 0; + output_term(msg, 4); + break; + + case 26: { + double my_float = 0.0; + msg[0] = ERL_DRV_FLOAT; + msg[1] = (ErlDrvTermData) &my_float; + output_term(msg, 2); + break; + } + + case 27: { + char buf[] = {131, 106}; /* [] */ + msg[0] = ERL_DRV_EXT2TERM; + msg[1] = (ErlDrvTermData) buf; + msg[2] = (ErlDrvTermData) sizeof(buf); + output_term(msg, 3); + break; + } + + case 28: { + ErlDrvUInt64 x = ~((ErlDrvUInt64) 0); + msg[0] = ERL_DRV_UINT64; + msg[1] = (ErlDrvTermData) &x; + output_term(msg, 2); + + break; + } + + case 29: { + ErlDrvUInt64 x = ((ErlDrvUInt64) 4711) << 32; + msg[0] = ERL_DRV_UINT64; + msg[1] = (ErlDrvTermData) &x; + output_term(msg, 2); + + break; + } + + case 30: { + ErlDrvUInt64 x = 4711; + msg[0] = ERL_DRV_UINT64; + msg[1] = (ErlDrvTermData) &x; + output_term(msg, 2); + + break; + } + + case 31: { + ErlDrvUInt64 x = 0; + msg[0] = ERL_DRV_UINT64; + msg[1] = (ErlDrvTermData) &x; + output_term(msg, 2); + + break; + } + + case 32: { + ErlDrvSInt64 x = ((((ErlDrvUInt64) 0x7fffffff) << 32) + | ((ErlDrvUInt64) 0xffffffff)); + msg[0] = ERL_DRV_INT64; + msg[1] = (ErlDrvTermData) &x; + output_term(msg, 2); + + break; + } + + case 33: { + ErlDrvSInt64 x = (ErlDrvSInt64) (((ErlDrvUInt64) 4711) << 32); + msg[0] = ERL_DRV_INT64; + msg[1] = (ErlDrvTermData) &x; + output_term(msg, 2); + + break; + } + + case 34: { + ErlDrvSInt64 x = 4711; + msg[0] = ERL_DRV_INT64; + msg[1] = (ErlDrvTermData) &x; + output_term(msg, 2); + + break; + } + + case 35: { + ErlDrvSInt64 x = 0; + msg[0] = ERL_DRV_INT64; + msg[1] = (ErlDrvTermData) &x; + output_term(msg, 2); + + break; + } + + case 36: { + ErlDrvSInt64 x = -1; + msg[0] = ERL_DRV_INT64; + msg[1] = (ErlDrvTermData) &x; + output_term(msg, 2); + + break; + } + + case 37: { + ErlDrvSInt64 x = -4711; + msg[0] = ERL_DRV_INT64; + msg[1] = (ErlDrvTermData) &x; + output_term(msg, 2); + + break; + } + + case 38: { + ErlDrvSInt64 x = ((ErlDrvSInt64) ((ErlDrvUInt64) 4711) << 32)*-1; + msg[0] = ERL_DRV_INT64; + msg[1] = (ErlDrvTermData) &x; + output_term(msg, 2); + + break; + } + + case 39: { + ErlDrvSInt64 x = ((ErlDrvSInt64) 1) << 63; + msg[0] = ERL_DRV_INT64; + msg[1] = (ErlDrvTermData) &x; + output_term(msg, 2); + + break; + } + + + case 127: /* Error cases */ + { + long refc; + ErlDrvBinary* bin = driver_alloc_binary(256); + + FAIL_TERM(msg, 0); + + msg[0] = ERL_DRV_LIST; + msg[1] = (ErlDrvTermData) 0; + FAIL_TERM(msg, 2); + + /* Not an atom */ + msg[0] = ERL_DRV_ATOM; + msg[1] = (ErlDrvTermData) driver_connected(erlang_port); + FAIL_TERM(msg, 2); + msg[0] = ERL_DRV_ATOM; + msg[1] = driver_term_nil; + FAIL_TERM(msg, 2); + + /* Not a pid */ + msg[0] = ERL_DRV_PID; + msg[1] = (ErlDrvTermData) driver_mk_atom("blurf"); + FAIL_TERM(msg, 2); + msg[0] = ERL_DRV_PID; + msg[1] = driver_term_nil; + FAIL_TERM(msg, 2); + + /* Not a port */ + msg[0] = ERL_DRV_PORT; + msg[1] = (ErlDrvTermData) driver_mk_atom("blurf"); + FAIL_TERM(msg, 2); + msg[0] = ERL_DRV_PORT; + msg[1] = driver_term_nil; + FAIL_TERM(msg, 2); + + /* Missing parameter on stack */ + msg[0] = ERL_DRV_STRING_CONS; + msg[1] = (ErlDrvTermData) "abc"; + msg[2] = (ErlDrvTermData) 3; + FAIL_TERM(msg, 3); + + /* + * The first binary reference is correct, the second is incorrect. + * There should not be any "binary leak". + */ + msg[0] = ERL_DRV_BINARY; + msg[1] = (ErlDrvTermData) bin; + msg[2] = (ErlDrvTermData) 256; + msg[3] = (ErlDrvTermData) 0; + msg[4] = ERL_DRV_BINARY; + msg[5] = (ErlDrvTermData) bin; + msg[6] = (ErlDrvTermData) 257; + msg[7] = (ErlDrvTermData) 0; + msg[8] = ERL_DRV_TUPLE; + msg[9] = (ErlDrvTermData) 2; + FAIL_TERM(msg, 10); + + msg[0] = ERL_DRV_BINARY; + msg[1] = (ErlDrvTermData) bin; + msg[2] = (ErlDrvTermData) 256; + msg[3] = (ErlDrvTermData) 0; + msg[4] = ERL_DRV_BINARY; + msg[5] = (ErlDrvTermData) bin; + msg[6] = (ErlDrvTermData) 256; + msg[7] = (ErlDrvTermData) 50; + msg[8] = ERL_DRV_TUPLE; + msg[9] = (ErlDrvTermData) 2; + FAIL_TERM(msg, 10); + + /* + * We have succefully built two binaries. We expect the ref count + * to be 1 (SMP) or 3 (non-SMP). + */ + refc = driver_binary_get_refc(bin); + if (refc > 3) { + char sbuf[128]; + sprintf(sbuf, "bad_refc:%d", refc); + driver_failure_atom(erlang_port, sbuf); + } + driver_free_binary(bin); + + + FAIL_TERM(msg, make_ext_term_list(msg, 1)); + + + /* + * Check that we fail for missing args. + * + * We setup valid terms but pass a too small size. We + * want valid terms since we want to verify that the + * failure really is due to the small size. + */ + msg[0] = ERL_DRV_ATOM; + msg[1] = (ErlDrvTermData) driver_mk_atom("an_atom"); + FAIL_TERM(msg, 1); + + msg[0] = ERL_DRV_INT; + msg[1] = (ErlDrvTermData) -4711; + FAIL_TERM(msg, 1); + + msg[0] = ERL_DRV_UINT; + msg[1] = (ErlDrvTermData) 4711; + FAIL_TERM(msg, 1); + + msg[0] = ERL_DRV_PORT; + msg[1] = driver_mk_port(erlang_port); + FAIL_TERM(msg, 1); + + { + char buf[] = "hejsan"; + ErlDrvBinary *dbin = driver_alloc_binary(sizeof(buf)-1); + if (!dbin) + driver_failure_posix(erlang_port, ENOMEM); + else { + memcpy((void *) dbin->orig_bytes, (void *) buf, sizeof(buf)-1); + msg[0] = ERL_DRV_BINARY; + msg[1] = (ErlDrvTermData) dbin; + msg[2] = (ErlDrvTermData) sizeof(buf)-1; + msg[3] = (ErlDrvTermData) 0; + FAIL_TERM(msg, 1); + FAIL_TERM(msg, 2); + FAIL_TERM(msg, 3); + driver_free_binary(dbin); + } + } + + { + char buf[] = "hoppsan"; + msg[0] = ERL_DRV_BUF2BINARY; + msg[1] = (ErlDrvTermData) buf; + msg[2] = (ErlDrvTermData) sizeof(buf)-1; + FAIL_TERM(msg, 1); + FAIL_TERM(msg, 2); + } + + { + char buf[] = "hippsan"; + msg[0] = ERL_DRV_STRING; + msg[1] = (ErlDrvTermData) buf; + msg[2] = (ErlDrvTermData) sizeof(buf)-1; + FAIL_TERM(msg, 1); + FAIL_TERM(msg, 2); + } + + msg[0] = ERL_DRV_TUPLE; + msg[1] = (ErlDrvTermData) 0; + FAIL_TERM(msg, 1); + + msg[0] = ERL_DRV_NIL; + msg[1] = ERL_DRV_LIST; + msg[2] = (ErlDrvTermData) 1; + FAIL_TERM(msg, 2); + + msg[0] = ERL_DRV_PID; + msg[1] = driver_connected(erlang_port); + FAIL_TERM(msg, 1); + + msg[0] = ERL_DRV_NIL; + msg[1] = ERL_DRV_STRING_CONS; + msg[2] = (ErlDrvTermData) ""; + msg[3] = (ErlDrvTermData) 0; + FAIL_TERM(msg, 2); + FAIL_TERM(msg, 3); + + { + double my_float = 0.0; + msg[0] = ERL_DRV_FLOAT; + msg[1] = (ErlDrvTermData) &my_float; + FAIL_TERM(msg, 1); + } + + { + char buf[] = {131, 106}; /* [] */ + msg[0] = ERL_DRV_EXT2TERM; + msg[1] = (ErlDrvTermData) buf; + msg[2] = (ErlDrvTermData) sizeof(buf); + FAIL_TERM(msg, 1); + FAIL_TERM(msg, 2); + } + + /* Signal end of test case */ + msg[0] = ERL_DRV_NIL; + driver_output_term(erlang_port, msg, 1); + } + break; + + default: + driver_failure_atom(erlang_port, "bad_request"); + break; + } +} + +static void output_term(ErlDrvTermData* msg, int len) +{ + if (driver_output_term(erlang_port, msg, len) <= 0) { + driver_failure_atom(erlang_port, "driver_output_term_failed"); + } +} + +static void fail_term(ErlDrvTermData* msg, int len, int line) +{ + int status = driver_output_term(erlang_port, msg, len); + + if (status == 1) { + char buf[1024]; + sprintf(buf, "%s:%d: unexpected success", __FILE__, line); + driver_failure_atom(erlang_port, buf); + } else if (status == 0) { + char buf[1024]; + sprintf(buf, "%s:%d: unexpected port error", __FILE__, line); + driver_failure_atom(erlang_port, buf); + } +} + +#include "ext_terms.h" + +/* + * <<131,103,100,0,12,97,110,111,100,101,64,103,111,114,98,97,103,0,0,0,36,0,0,0,0,1>> + * is a valid pid: <0.36.0> + * + * We replace the nodename tag (atom tag: 100) with a pid tag (103) to get an + * invalid pid. + */ +static unsigned char bad_ext_term[] = { + 131,103,103,0,12,97,110,111,100,101,64,103,111,114,98,97,103,0,0,0,36,0,0,0,0,1 + /* ^ + * | + * The bad tag. + */ +}; + +static int make_ext_term_list(ErlDrvTermData *td, int bad) +{ + int tdix = 0; + int i; + for (i = 0; i < NO_OF_EXT_TERMS; i++) { + td[tdix++] = ERL_DRV_EXT2TERM; + td[tdix++] = (ErlDrvTermData) &ext_terms[i].ext[0]; + td[tdix++] = (ErlDrvTermData) ext_terms[i].ext_size; + td[tdix++] = ERL_DRV_EXT2TERM; + td[tdix++] = (ErlDrvTermData) &ext_terms[i].cext[0]; + td[tdix++] = (ErlDrvTermData) ext_terms[i].cext_size; + td[tdix++] = ERL_DRV_TUPLE; + td[tdix++] = (ErlDrvTermData) 2; + } + if (bad) { /* Include a bad ext term */ + td[tdix++] = ERL_DRV_EXT2TERM; + td[tdix++] = (ErlDrvTermData) &bad_ext_term[0]; + td[tdix++] = (ErlDrvTermData) sizeof(bad_ext_term); + } + td[tdix++] = ERL_DRV_NIL; + td[tdix++] = ERL_DRV_LIST; + td[tdix++] = (ErlDrvTermData) (NO_OF_EXT_TERMS + (bad ? 2 : 1)); + return tdix; +} diff --git a/erts/emulator/test/sensitive_SUITE.erl b/erts/emulator/test/sensitive_SUITE.erl new file mode 100644 index 0000000000..458275af81 --- /dev/null +++ b/erts/emulator/test/sensitive_SUITE.erl @@ -0,0 +1,461 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(sensitive_SUITE). + +-include("test_server.hrl"). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + stickiness/1,send_trace/1,recv_trace/1,proc_trace/1,call_trace/1, + meta_trace/1,running_trace/1,gc_trace/1,seq_trace/1, + t_process_info/1,t_process_display/1,save_calls/1]). + +-export([remote_process_display/0,an_exported_function/1]). + +-import(lists, [keysearch/3,foreach/2,sort/1]). + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog = ?t:timetrap(?t:minutes(5)), + [{watchdog,Dog}|Config]. + +fin_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +all(suite) -> + [stickiness,send_trace,recv_trace,proc_trace,call_trace, + meta_trace,running_trace,gc_trace,seq_trace, + t_process_info,t_process_display,save_calls]. + +stickiness(Config) when is_list(Config) -> + ?line {Tracer,Mref} = spawn_monitor(fun() -> + receive after infinity -> ok end + end), + ?line false = process_flag(sensitive, true), + put(foo, bar), + + Flags = sort([send,'receive',procs,call,running,garbage_collection, + set_on_spawn,set_on_first_spawn,set_on_link,set_on_first_link]), + ?line foreach(fun(F) -> + 1 = erlang:trace(self(), true, [F,{tracer,Tracer}]) + end, Flags), + ?line foreach(fun(F) -> + 1 = erlang:trace(self(), false, [F,{tracer,Tracer}]) + end, Flags), + ?line 1 = erlang:trace(self(), true, [{tracer,Tracer}|Flags]), + ?line 1 = erlang:trace(self(), false, [{tracer,Tracer}|Flags]), + + ?line {messages,[]} = process_info(Tracer, messages), + exit(Tracer, kill), + receive {'DOWN',Mref,_,_,_} -> ok end, + + case process_info(self(), dictionary) of + {dictionary,[]} -> ok; + {dictionary,_} -> ?line ?t:fail(sensitive_flag_cleared) + end, + + NewTracer = spawn_link(fun() -> receive after infinity -> ok end end), + ?line 1 = erlang:trace(self(), true, [{tracer,NewTracer}|Flags]), + ?line Flags = sort(element(2, erlang:trace_info(self(), flags))), + ?line {tracer,NewTracer} = erlang:trace_info(self(), tracer), + + %% Process still sensitive. Tracer should disappear when we clear + %% all trace flags. + ?line 1 = erlang:trace(self(), false, [{tracer,NewTracer}|Flags]), + ?line {tracer,[]} = erlang:trace_info(self(), tracer), + + ?line unlink(NewTracer), exit(NewTracer, kill), + ok. + +send_trace(Config) when is_list(Config) -> + ?line {Dead,Mref} = spawn_monitor(fun() -> ok end), + receive {'DOWN',Mref,_,_,_} -> ok end, + ?line Tracer = spawn_link(fun() -> receive after infinity -> ok end end), + ?line Sink = spawn_link(fun() -> receive after infinity -> ok end end), + Self = self(), + + ?line 1 = erlang:trace(self(), true, [send,{tracer,Tracer}]), + ?line Dead ! before, + ?line Sink ! before, + ?line false = process_flag(sensitive, true), + ?line Sink ! {blurf,lists:seq(1, 50)}, + ?line true = process_flag(sensitive, true), + ?line Sink ! lists:seq(1, 100), + ?line Dead ! forget_me, + ?line true = process_flag(sensitive, false), + ?line Sink ! after1, + ?line false = process_flag(sensitive, false), + ?line Sink ! after2, + ?line Dead ! after2, + ?line wait_trace(Self), + + ?line {messages,Messages} = process_info(Tracer, messages), + ?line [{trace,Self,send_to_non_existing_process,before,Dead}, + {trace,Self,send,before,Sink}, + {trace,Self,send,after1,Sink}, + {trace,Self,send,after2,Sink}, + {trace,Self,send_to_non_existing_process,after2,Dead}] = Messages, + + ?line unlink(Tracer), exit(Tracer, kill), + ?line unlink(Sink), exit(Sink, kill), + ok. + +recv_trace(Config) when is_list(Config) -> + Parent = self(), + ?line Tracer = spawn_link(fun() -> receive after infinity -> ok end end), + ?line Sender = spawn_link(fun() -> recv_trace_sender(Parent) end), + + ?line 1 = erlang:trace(self(), true, ['receive',{tracer,Tracer}]), + + Sender ! 1, + receive a -> wait_trace(Sender) end, + + ?line false = process_flag(sensitive, true), + + Sender ! 2, + receive {b,[x,y,z]} -> wait_trace(Sender) end, + + ?line true = process_flag(sensitive, false), + + Sender ! 3, + receive c -> wait_trace(Sender) end, + + ?line {messages,Messages} = process_info(Tracer, messages), + [{trace,Parent,'receive',a}, + {trace,Parent,'receive',{trace_delivered,_,_}}, + {trace,Parent,'receive',c}, + {trace,Parent,'receive',{trace_delivered,_,_}}] = Messages, + + ?line unlink(Tracer), exit(Tracer, kill), + ?line unlink(Sender), exit(Sender, kill), + ok. + +recv_trace_sender(Pid) -> + receive + 1 -> Pid ! a; + 2 -> Pid ! {b,[x,y,z]}; + 3 -> Pid ! c + end, + recv_trace_sender(Pid). + +proc_trace(Config) when is_list(Config) -> + Self = self(), + ?line Tracer = spawn_link(fun() -> receive after infinity -> ok end end), + + ?line 1 = erlang:trace(self(), true, [procs,{tracer,Tracer}]), + ?line false = process_flag(sensitive, true), + + spawn(fun() -> ok end), + ?line register(nisse, self()), + ?line unregister(nisse), + ?line link(Tracer), + ?line unlink(Tracer), + ?line Linker0 = spawn_link(fun() -> ok end), + Mref0 = erlang:monitor(process, Linker0), + + ?line {_,Mref} = spawn_monitor(fun() -> link(Self), unlink(Self) end), + + receive {'DOWN',Mref0,_,_,_} -> ok end, + + receive {'DOWN',Mref,_,_,_} -> ok end, + + ?line true = process_flag(sensitive, false), + + Dead = spawn(fun() -> ok end), + ?line register(arne, self()), + ?line unregister(arne), + ?line {Linker,Mref2} = spawn_monitor(fun() -> link(Self), unlink(Self) end), + receive {'DOWN',Mref2,_,_,_} -> ok end, + ?line Last = spawn_link(fun() -> ok end), + receive after 10 -> ok end, + ?line wait_trace(all), + ?line {messages,Messages} = process_info(Tracer, messages), + [{trace,Self,spawn,Dead,{erlang,apply,_}}, + {trace,Self,register,arne}, + {trace,Self,unregister,arne}, + {trace,Self,spawn,Linker,_}, + {trace,Self,getting_linked,Linker}, + {trace,Self,getting_unlinked,Linker}, + {trace,Self,spawn,Last,_}, + {trace,Self,link,Last}, + {trace,Self,getting_unlinked,Last}] = Messages, + + ?line unlink(Tracer), exit(Tracer, kill), + ok. + +call_trace(Config) when is_list(Config) -> + Self = self(), + ?line Tracer = spawn_link(fun() -> receive after infinity -> ok end end), + + ?line 1 = erlang:trace(self(), true, [call,{tracer,Tracer}]), + ?line 1 = erlang:trace_pattern({?MODULE,an_exported_function,1}, + true, [global]), + ?line 1 = erlang:trace_pattern({erlang,list_to_binary,1}, true, [global]), + ?line 1 = erlang:trace_pattern({erlang,binary_to_list,1}, true, [local]), + ?line Local = erlang:trace_pattern({?MODULE,'_','_'}, true, [local]), + + ?line false = process_flag(sensitive, true), + ?line {ok,42} = a_local_function(42), + ?line 7 = an_exported_function(6), + ?line <<7,8,9,10>> = list_to_binary(id([7,8,9,10])), + ?line [42,43] = binary_to_list(id(<<42,43>>)), + ?line true = process_flag(sensitive, false), + + ?line {ok,{a,b}} = a_local_function({a,b}), + ?line 1 = an_exported_function(0), + ?line <<1,2,3>> = list_to_binary(id([1,2,3])), + ?line [42,43,44] = binary_to_list(id(<<42,43,44>>)), + + ?line wait_trace(Self), + + ?line {messages,Messages} = process_info(Tracer, messages), + ?line [{trace,Self,call,{?MODULE,a_local_function,[{a,b}]}}, + {trace,Self,call,{?MODULE,an_exported_function,[0]}}, + {trace,Self,call,{?MODULE,id,[_]}}, + {trace,Self,call,{erlang,list_to_binary,[[1,2,3]]}}, + {trace,Self,call,{sensitive_SUITE,id,[<<42,43,44>>]}}, + {trace,Self,call,{erlang,binary_to_list,[<<42,43,44>>]}}, + {trace,Self,call,{?MODULE,wait_trace,[Self]}}] = Messages, + + ?line Local = erlang:trace_pattern({?MODULE,'_','_'}, false, [local]), + ?line erlang:trace_pattern({erlang,'_','_'}, false, [local]), + ?line erlang:trace_pattern({'_','_','_'}, false, [global]), + + ?line unlink(Tracer), exit(Tracer, kill), + ok. + +meta_trace(Config) when is_list(Config) -> + Self = self(), + ?line Tracer = spawn_link(fun() -> receive after infinity -> ok end end), + + ?line Local = erlang:trace_pattern({?MODULE,'_','_'}, true, [{meta,Tracer}]), + ?line 1 = erlang:trace_pattern({erlang,list_to_binary,1}, true, [{meta,Tracer}]), + + ?line false = process_flag(sensitive, true), + ?line {ok,blurf} = a_local_function(blurf), + ?line 100 = an_exported_function(99), + ?line <<8,9,10>> = list_to_binary(id([8,9,10])), + ?line true = process_flag(sensitive, false), + + ?line {ok,{x,y}} = a_local_function({x,y}), + ?line 1 = an_exported_function(0), + ?line <<10>> = list_to_binary(id([10])), + ?line wait_trace(Self), + + ?line Local = erlang:trace_pattern({?MODULE,'_','_'}, false, [meta]), + ?line 1 = erlang:trace_pattern({erlang,list_to_binary,1}, false, [meta]), + ?line a_local_function(0), + + ?line {messages,Messages} = process_info(Tracer, messages), + ?line [{trace_ts,Self,call,{?MODULE,a_local_function,[{x,y}]},{_,_,_}}, + {trace_ts,Self,call,{?MODULE,an_exported_function,[0]},{_,_,_}}, + {trace_ts,Self,call,{?MODULE,id,[_]},{_,_,_}}, + {trace_ts,Self,call,{erlang,list_to_binary,[[10]]},{_,_,_}}, + {trace_ts,Self,call,{?MODULE,wait_trace,[Self]},{_,_,_}}] = Messages, + + ?line unlink(Tracer), exit(Tracer, kill), + ok. + +a_local_function(A) -> + {ok,A}. + +an_exported_function(X) -> + X+1. + +running_trace(Config) when is_list(Config) -> + Self = self(), + ?line Tracer = spawn_link(fun() -> receive after infinity -> ok end end), + + ?line false = process_flag(sensitive, true), + ?line 1 = erlang:trace(Self, true, [running,{tracer,Tracer}]), + erlang:yield(), erlang:yield(), erlang:yield(), erlang:yield(), + erlang:yield(), erlang:yield(), erlang:yield(), erlang:yield(), + ?line true = process_flag(sensitive, false), + erlang:yield(), + ?line 1 = erlang:trace(Self, false, [running,{tracer,Tracer}]), + + ?line wait_trace(Self), + ?line {messages,Messages} = process_info(Tracer, messages), + ?line [{trace,Self,out,{sensitive_SUITE,running_trace,1}}, + {trace,Self,in,{sensitive_SUITE,running_trace,1}}] = Messages, + + ?line unlink(Tracer), exit(Tracer, kill), + ok. + +gc_trace(Config) when is_list(Config) -> + Self = self(), + ?line Tracer = spawn_link(fun() -> receive after infinity -> ok end end), + + ?line false = process_flag(sensitive, true), + ?line 1 = erlang:trace(Self, true, [garbage_collection,{tracer,Tracer}]), + erlang:garbage_collect(), erlang:garbage_collect(), + erlang:garbage_collect(), erlang:garbage_collect(), + erlang:garbage_collect(), erlang:garbage_collect(), + erlang:garbage_collect(), erlang:garbage_collect(), + ?line true = process_flag(sensitive, false), + erlang:garbage_collect(), + ?line 1 = erlang:trace(Self, false, [garbage_collection,{tracer,Tracer}]), + + ?line wait_trace(Self), + ?line {messages,Messages} = process_info(Tracer, messages), + ?line [{trace,Self,gc_start,_},{trace,Self,gc_end,_}] = Messages, + + ?line unlink(Tracer), exit(Tracer, kill), + ok. + +seq_trace(Config) when is_list(Config) -> + Self = self(), + ?line Tracer = spawn_link(fun() -> receive after infinity -> ok end end), + ?line seq_trace:set_system_tracer(Tracer), + + ?line false = process_flag(sensitive, true), + + ?line Echo = spawn_link(fun() -> + receive + {Pid,Message} -> + Pid ! {reply,Message} + end + end), + ?line Sender = spawn_link(fun() -> + seq_trace:set_token(label, 42), + seq_trace:set_token('receive', true), + seq_trace:set_token(send, true), + seq_trace:set_token(print, true), + seq_trace:print(42, "trace started"), + Self ! blurf + end), + seq_trace:set_token(label, 17), + seq_trace:set_token('receive', true), + seq_trace:set_token(send, true), + seq_trace:set_token(print, true), + seq_trace:print(17, "trace started"), + Echo ! {Self,hello}, + receive {reply,hello} -> ok end, + receive blurf -> ok end, + + ?line wait_trace(all), + + ?line {messages,Messages} = process_info(Tracer, messages), + ?line [{seq_trace,17,{'receive',{0,2},Self,Echo,{Self,hello}}}, + {seq_trace,17,{send,{2,3},Echo,Self,{reply,hello}}}] = + [M || {seq_trace,17,_}=M <- Messages], + + ?line [{seq_trace,42,{print,{0,1},Sender,[],"trace started"}}, + {seq_trace,42,{send,{0,2},Sender,Self,blurf}}] = + [M || {seq_trace,42,_}=M <- Messages], + + ?line unlink(Tracer), exit(Tracer, kill), + ?line unlink(Echo), exit(Echo, kill), + ?line unlink(Sender), exit(Sender, kill), + ok. + +t_process_info(Config) when is_list(Config) -> + Parent = self(), + ?line Pid = spawn_link(fun() -> + put(foo, bar), + false = process_flag(sensitive, true), + Parent ! go, + receive + revert -> + true = process_flag(sensitive, false), + Parent ! go_again, + receive never -> ok end + end end), + receive go -> ok end, + + ?line put(foo, bar), + ?line self() ! Pid ! {i,am,a,message}, + + ?line false = process_flag(sensitive, true), + ?line t_process_info_suppressed(self()), + ?line t_process_info_suppressed(Pid), + + ?line true = process_flag(sensitive, false), + Pid ! revert, + receive go_again -> ok end, + + ?line t_process_info_normal(self()), + ?line t_process_info_normal(Pid), + ok. + +t_process_info_suppressed(Pid) -> + [] = my_process_info(Pid, dictionary), + <<>> = my_process_info(Pid, backtrace), + [] = my_process_info(Pid, messages). + +t_process_info_normal(Pid) -> + {value,{foo,bar}} = keysearch(foo, 1, my_process_info(Pid, dictionary)), + case process_info(Pid, backtrace) of + {backtrace,Bin} when size(Bin) > 20 -> ok + end, + [{i,am,a,message}] = my_process_info(Pid, messages). + +my_process_info(Pid, Tag) -> + {Tag,Value} = process_info(Pid, Tag), + All = process_info(Pid), + case keysearch(Tag, 1, All) of + false -> Value; + {value,{Tag,Value}} -> Value + end. + +t_process_display(Config) when is_list(Config) -> + ?line Dir = filename:dirname(code:which(?MODULE)), + ?line Cmd = atom_to_list(lib:progname()) ++ " -noinput -pa " ++ Dir ++ + " -run " ++ ?MODULE_STRING ++ " remote_process_display", + ?line io:put_chars(Cmd), + ?line P = open_port({spawn,Cmd}, [in,stderr_to_stdout,eof]), + <<"done",_/binary>> = get_all(P), + ok. + +remote_process_display() -> + false = process_flag(sensitive, true), + erlang:process_display(self(), backtrace), + erlang:display(done), + receive after 10 -> ok end, + init:stop(). + +get_all(P) -> + get_all(P, []). + +get_all(P, Acc) -> + receive + {P,{data,S}} -> + get_all(P, [Acc|S]); + {P,eof} -> + iolist_to_binary(Acc) + end. + +save_calls(Config) when is_list(Config) -> + process_flag(save_calls, 10), + + false = process_flag(sensitive, true), + ?line {last_calls,LastCalls} = process_info(self(), last_calls), + ?line [{erlang,process_flag,2}] = LastCalls, + ?line [2,4,6] = lists:map(fun(E) -> 2*E end, [1,2,3]), + ?line {last_calls,LastCalls} = process_info(self(), last_calls), + ok. + +wait_trace(Pid) -> + Ref = erlang:trace_delivered(Pid), + receive + {trace_delivered,Pid,Ref} -> ok + end. + +id(I) -> I. + diff --git a/erts/emulator/test/signal_SUITE.erl b/erts/emulator/test/signal_SUITE.erl new file mode 100644 index 0000000000..e9103ca3c1 --- /dev/null +++ b/erts/emulator/test/signal_SUITE.erl @@ -0,0 +1,544 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%%------------------------------------------------------------------- +%%% File : signal_SUITE.erl +%%% Author : Rickard Green <[email protected]> +%%% Description : Test signals +%%% +%%% Created : 10 Jul 2006 by Rickard Green <[email protected]> +%%%------------------------------------------------------------------- +-module(signal_SUITE). +-author('[email protected]'). + +-define(DEFAULT_TIMEOUT_SECONDS, 120). + +%-define(line_trace, 1). +-include("test_server.hrl"). +-export([all/1]). + +% Test cases +-export([xm_sig_order/1, + pending_exit_unlink_process/1, + pending_exit_unlink_dist_process/1, + pending_exit_unlink_port/1, + pending_exit_trap_exit/1, + pending_exit_receive/1, + pending_exit_exit/1, + pending_exit_gc/1, + pending_exit_is_process_alive/1, + pending_exit_process_display/1, + pending_exit_process_info_1/1, + pending_exit_process_info_2/1, + pending_exit_group_leader/1, + exit_before_pending_exit/1]). + +-export([init_per_testcase/2, fin_per_testcase/2, end_per_suite/1]). + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + ?line Dog = ?t:timetrap(?t:seconds(?DEFAULT_TIMEOUT_SECONDS)), + available_internal_state(true), + ?line [{testcase, Func},{watchdog, Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + ?line Dog = ?config(watchdog, Config), + ?line ?t:timetrap_cancel(Dog). + +end_per_suite(_Config) -> + available_internal_state(true), + erts_debug:set_internal_state(not_running_optimization, true), + available_internal_state(false). + +all(suite) -> + [xm_sig_order, + pending_exit_unlink_process, + pending_exit_unlink_dist_process, + pending_exit_unlink_port, + pending_exit_trap_exit, + pending_exit_receive, + pending_exit_trap_exit, + pending_exit_gc, + pending_exit_is_process_alive, + pending_exit_process_display, + pending_exit_process_info_1, + pending_exit_process_info_2, + pending_exit_group_leader, + exit_before_pending_exit]. + +xm_sig_order(doc) -> ["Test that exit signals and messages are received " + "in correct order"]; +xm_sig_order(suite) -> []; +xm_sig_order(Config) when is_list(Config) -> + ?line LNode = node(), + ?line repeat(fun () -> xm_sig_order_test(LNode) end, 1000), + ?line {ok, RNode} = start_node(Config), + ?line repeat(fun () -> xm_sig_order_test(RNode) end, 1000), + ?line stop_node(RNode), + ?line ok. + + +xm_sig_order_test(Node) -> + ?line P = spawn(Node, fun () -> xm_sig_order_proc() end), + ?line M = erlang:monitor(process, P), + ?line P ! may_reach, + ?line P ! may_reach, + ?line P ! may_reach, + ?line exit(P, good_signal_order), + ?line P ! may_not_reach, + ?line P ! may_not_reach, + ?line P ! may_not_reach, + ?line receive + {'DOWN', M, process, P, R} -> + ?line good_signal_order = R + end. + +xm_sig_order_proc() -> + receive + may_not_reach -> exit(bad_signal_order); + may_reach -> ok + after 0 -> ok + end, + xm_sig_order_proc(). + +pending_exit_unlink_process(doc) -> []; +pending_exit_unlink_process(suite) -> []; +pending_exit_unlink_process(Config) when is_list(Config) -> + ?line pending_exit_test(self(), unlink). + +pending_exit_unlink_dist_process(doc) -> []; +pending_exit_unlink_dist_process(suite) -> []; +pending_exit_unlink_dist_process(Config) when is_list(Config) -> + ?line {ok, Node} = start_node(Config), + ?line From = spawn(Node, fun () -> receive after infinity -> ok end end), + ?line Res = pending_exit_test(From, unlink), + ?line stop_node(Node), + ?line Res. + +pending_exit_unlink_port(doc) -> []; +pending_exit_unlink_port(suite) -> []; +pending_exit_unlink_port(Config) when is_list(Config) -> + ?line pending_exit_test(hd(erlang:ports()), unlink). + +pending_exit_trap_exit(doc) -> []; +pending_exit_trap_exit(suite) -> []; +pending_exit_trap_exit(Config) when is_list(Config) -> + ?line pending_exit_test(self(), trap_exit). + +pending_exit_receive(doc) -> []; +pending_exit_receive(suite) -> []; +pending_exit_receive(Config) when is_list(Config) -> + ?line pending_exit_test(self(), 'receive'). + +pending_exit_exit(doc) -> []; +pending_exit_exit(suite) -> []; +pending_exit_exit(Config) when is_list(Config) -> + ?line pending_exit_test(self(), exit). + +pending_exit_gc(doc) -> []; +pending_exit_gc(suite) -> []; +pending_exit_gc(Config) when is_list(Config) -> + ?line pending_exit_test(self(), gc). + +pending_exit_test(From, Type) -> + ?line case catch erlang:system_info(smp_support) of + true -> + ?line OTE = process_flag(trap_exit, true), + ?line Ref = make_ref(), + ?line Master = self(), + ?line ExitBySignal = case Type of + gc -> + lists:duplicate(10000, + exit_by_signal); + _ -> + exit_by_signal + end, + ?line Pid = spawn_link( + fun () -> + receive go -> ok end, + false = have_pending_exit(), + exit = fake_exit(From, + self(), + ExitBySignal), + true = have_pending_exit(), + Master ! {self(), Ref, Type}, + case Type of + gc -> + force_gc(), + erlang:yield(); + unlink -> + unlink(From); + trap_exit -> + process_flag(trap_exit, true); + 'receive' -> + receive _ -> ok + after 0 -> ok + end; + exit -> + ok + end, + exit(exit_by_myself) + end), + ?line Mon = erlang:monitor(process, Pid), + ?line Pid ! go, + ?line Reason = receive + {'DOWN', Mon, process, Pid, R} -> + ?line receive + {Pid, Ref, Type} -> + ?line ok + after 0 -> + ?line ?t:fail(premature_exit) + end, + ?line case Type of + exit -> + ?line exit_by_myself = R; + _ -> + ?line ExitBySignal = R + end + end, + ?line receive + {'EXIT', Pid, R2} -> + ?line Reason = R2 + end, + ?line process_flag(trap_exit, OTE), + ?line ok, + {comment, + "Test only valid with current SMP emulator."}; + _ -> + {skipped, + "SMP support not enabled. " + "Test only valid with current SMP emulator."} + end. + + + +exit_before_pending_exit(doc) -> []; +exit_before_pending_exit(suite) -> []; +exit_before_pending_exit(Config) when is_list(Config) -> + %% This is a testcase testcase very specific to the smp + %% implementation as it is of the time of writing. + %% + %% The testcase tries to check that a process can + %% exit by itself even though it has a pending exit. + ?line OTE = process_flag(trap_exit, true), + ?line Master = self(), + ?line Tester = spawn_link( + fun () -> + Opts = case {erlang:system_info(run_queues), + erlang:system_info(schedulers_online)} of + {RQ, SO} when RQ =:= 1; SO =:= 1 -> []; + _ -> + process_flag(scheduler, 1), + [{scheduler, 2}] + end, + P = self(), + Exiter = spawn_opt(fun () -> + receive + {exit_me, P, R} -> + exit(P, R) + end + end, Opts), + erlang:yield(), + Exiter ! {exit_me, self(), exited_by_exiter}, + %% We want to get a pending exit + %% before we exit ourselves. We + %% don't want to be scheduled out + %% since we will then see the + %% pending exit. + %% + %% Do something that takes + %% relatively long time but + %% consumes few reductions... + repeat(fun() -> erlang:system_info(procs) end,10), + %% ... then exit. + Master ! {self(), + pending_exit, + have_pending_exit()}, + exit(exited_by_myself) + end), + ?line PendingExit = receive {Tester, pending_exit, PE} -> PE end, + ?line receive + {'EXIT', Tester, exited_by_myself} -> + ?line process_flag(trap_exit, OTE), + ?line ok; + Msg -> + ?line ?t:fail({unexpected_message, Msg}) + end, + NoScheds = integer_to_list(erlang:system_info(schedulers_online)), + {comment, + "Was " + ++ case PendingExit of + true -> ""; + false ->"*not*" + end ++ " able to trigger a pending exit. " + ++ "Running on " ++ NoScheds ++ " scheduler(s). " + ++ "This test is only interesting with at least two schedulers."}. + +-define(PE_INFO_REPEAT, 100). + +pending_exit_is_process_alive(Config) when is_list(Config) -> + ?line S = exit_op_test_init(), + ?line TestFun = fun (P) -> false = is_process_alive(P) end, + ?line repeated_exit_op_test(TestFun, ?PE_INFO_REPEAT), + ?line verify_pending_exit_success(S), + ?line comment(). + +pending_exit_process_info_1(Config) when is_list(Config) -> + ?line S = exit_op_test_init(), + ?line TestFun = fun (P) -> + undefined = process_info(P) + end, + ?line repeated_exit_op_test(TestFun, ?PE_INFO_REPEAT), + ?line verify_pending_exit_success(S), + ?line comment(). + +pending_exit_process_info_2(Config) when is_list(Config) -> + ?line S0 = exit_op_test_init(), + ?line repeated_exit_op_test(fun (P) -> + undefined = process_info(P, messages) + end, ?PE_INFO_REPEAT), + ?line S1 = verify_pending_exit_success(S0), + ?line repeated_exit_op_test(fun (P) -> + undefined = process_info(P, status) + end, ?PE_INFO_REPEAT), + ?line S2 = verify_pending_exit_success(S1), + ?line repeated_exit_op_test(fun (P) -> + undefined = process_info(P, links) + end, ?PE_INFO_REPEAT), + ?line S3 = verify_pending_exit_success(S2), + ?line repeated_exit_op_test(fun (P) -> + undefined = process_info(P, [messages]) + end, ?PE_INFO_REPEAT), + ?line S4 = verify_pending_exit_success(S3), + ?line repeated_exit_op_test(fun (P) -> + undefined = process_info(P, [status]) + end, ?PE_INFO_REPEAT), + ?line S5 = verify_pending_exit_success(S4), + ?line repeated_exit_op_test(fun (P) -> + undefined = process_info(P, [links]) + end, ?PE_INFO_REPEAT), + ?line S6 = verify_pending_exit_success(S5), + ?line repeated_exit_op_test(fun (P) -> + undefined = process_info(P, [status, + links]) + end, ?PE_INFO_REPEAT), + ?line S7 = verify_pending_exit_success(S6), + ?line repeated_exit_op_test(fun (P) -> + undefined = process_info(P, [messages, + status]) + end, ?PE_INFO_REPEAT), + ?line S8 = verify_pending_exit_success(S7), + ?line repeated_exit_op_test(fun (P) -> + undefined = process_info(P, [messages, + links]) + end, ?PE_INFO_REPEAT), + ?line S9 = verify_pending_exit_success(S8), + ?line repeated_exit_op_test( + fun (P) -> + undefined = process_info(P, [message_queue_len, + status]) + end, ?PE_INFO_REPEAT), + ?line S10 = verify_pending_exit_success(S9), + ?line repeated_exit_op_test(fun (P) -> + undefined = process_info(P, [messages, + links, + status]) + end, ?PE_INFO_REPEAT), + ?line verify_pending_exit_success(S10), + ?line comment(). + +pending_exit_process_display(Config) when is_list(Config) -> + ?line S = exit_op_test_init(), + ?line TestFun = fun (P) -> + badarg = try + erlang:process_display(P, backtrace) + catch + error:badarg -> badarg + end + end, + ?line repeated_exit_op_test(TestFun, ?PE_INFO_REPEAT), + ?line verify_pending_exit_success(S), + ?line comment(). + +pending_exit_group_leader(Config) when is_list(Config) -> + ?line S = exit_op_test_init(), + ?line TestFun = fun (P) -> + badarg = try + group_leader(self(), P) + catch + error:badarg -> badarg + end + end, + ?line repeated_exit_op_test(TestFun, ?PE_INFO_REPEAT), + ?line verify_pending_exit_success(S), + ?line comment(). + +%% +%% -- Internal utils -------------------------------------------------------- +%% +exit_op_test_init() -> + put(no_pending_exit_success, 0), + put(no_pending_exit_tries, 0), + {case {erlang:system_info(run_queues), + erlang:system_info(schedulers_online)} of + {RQ, SO} when RQ =:= 1; SO =:= 1 -> false; + _ -> true + end, 0, 0}. + +verify_pending_exit_success({false, _, _} = S) -> + S; +verify_pending_exit_success({true, S, T}) -> + NewS = get(no_pending_exit_success), + NewT = get(no_pending_exit_tries), + case NewT =:= T of + true -> ok; + _ -> case NewS > S of + true -> ok; + _ -> exit(no_pending_exits) + end + end, + {true, NewS, NewT}. + +comment() -> + {comment, + "Pending exit trigger ratio " + ++ integer_to_list(get(no_pending_exit_success)) + ++ "/" + ++ integer_to_list(get(no_pending_exit_tries)) + ++ "." + ++ case get(not_running_opt_test) of + true -> " No 'not running optimization' to disable."; + _ -> "" + end}. + +repeated_exit_op_test(TestFun, N) -> + WorkFun0 = fun () -> + lists:sort(lists:reverse(lists:seq(1, 1000))) + end, + repeat(fun () -> exit_op_test(TestFun, WorkFun0) end, N), + try erts_debug:set_internal_state(not_running_optimization, false) of + Bool when Bool == true; Bool == false -> + WorkFun1 = fun () -> + erts_debug:set_internal_state(sleep, 0), + lists:sort(lists:reverse(lists:seq(1, 1000))) + end, + repeat(fun () -> + exit_op_test(TestFun, WorkFun1) + end, N) + catch + error:notsup -> put(not_running_opt_test, true) + after + catch erts_debug:set_internal_state(not_running_optimization, true) + end. + +exit_op_test(TestFun, WorkFun) -> + Opts = case {erlang:system_info(run_queues), + erlang:system_info(schedulers_online)} of + {RQ, SO} when RQ =:= 1; SO =:= 1 -> []; + _ -> + process_flag(scheduler, 1), + [{scheduler, 2}] + end, + Master = self(), + Going = make_ref(), + P = spawn_opt(fun () -> + loop(10, WorkFun), + Master ! Going, + loop(infinity, WorkFun) + end, Opts), + receive Going -> ok end, + loop(10, WorkFun), + erlang:yield(), + exit(P, bang), + PE0 = have_pending_exit(P), + TestFun(P), + PE = case PE0 of + true -> true; + _ -> false + end, + case {PE, get(no_pending_exit_success), get(no_pending_exit_tries)} of + {true, undefined, undefined} -> + put(no_pending_exit_success, 1), + put(no_pending_exit_tries, 1); + {false, undefined, undefined} -> + put(no_pending_exit_success, 0), + put(no_pending_exit_tries, 1); + {true, S, T} -> + put(no_pending_exit_success, S+1), + put(no_pending_exit_tries, T+1); + {false, _S, T} -> + put(no_pending_exit_tries, T+1) + end, + ok. + +loop(infinity, WorkFun) -> + do_loop(infinity, WorkFun); +loop(0, _WorkFun) -> + ok; +loop(N, WorkFun) when is_integer(N) -> + do_loop(N-1, WorkFun). + +do_loop(N, WorkFun) -> + WorkFun(), + loop(N, WorkFun). + +repeat(_Fun, N) when is_integer(N), N =< 0 -> + ok; +repeat(Fun, N) when is_integer(N) -> + Fun(), + repeat(Fun, N-1). + +start_node(Config) -> + {A, B, C} = now(), + Name = list_to_atom(atom_to_list(?MODULE) + ++ "-" ++ atom_to_list(?config(testcase, Config)) + ++ "-" ++ integer_to_list(A) + ++ "-" ++ integer_to_list(B) + ++ "-" ++ integer_to_list(C)), + Pa = filename:dirname(code:which(?MODULE)), + ?t:start_node(Name, slave, [{args, "-pa " ++ Pa}]). + +stop_node(Node) -> + ?t:stop_node(Node). + +have_pending_exit() -> + have_pending_exit(self()). + +have_pending_exit(Pid) -> + erts_debug:get_internal_state({have_pending_exit, Pid}). + +force_gc() -> + erts_debug:set_internal_state(force_gc, self()). + +fake_exit(From, To, Reason) -> + erts_debug:set_internal_state(send_fake_exit_signal, {From, To, Reason}). + +available_internal_state(Bool) when Bool == true; Bool == false -> + case {Bool, + (catch erts_debug:get_internal_state(available_internal_state))} of + {true, true} -> + true; + {false, true} -> + erts_debug:set_internal_state(available_internal_state, false), + true; + {true, _} -> + erts_debug:set_internal_state(available_internal_state, true), + false; + {false, _} -> + false + end. diff --git a/erts/emulator/test/statistics_SUITE.erl b/erts/emulator/test/statistics_SUITE.erl new file mode 100644 index 0000000000..bc12821887 --- /dev/null +++ b/erts/emulator/test/statistics_SUITE.erl @@ -0,0 +1,341 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(statistics_SUITE). + +%% Tests the statistics/1 bif. + +-export([all/1, + init_per_testcase/2, + fin_per_testcase/2, + wall_clock/1, wall_clock_zero_diff/1, wall_clock_update/1, + runtime/1, runtime_zero_diff/1, runtime_zero_update/1, + runtime_update/1, runtime_diff/1, + run_queue/1, run_queue_one/1, + reductions/1, reductions_big/1, garbage_collection/1, io/1, + badarg/1]). + +%% Internal exports. + +-export([hog/1]). + +-include("test_server.hrl"). + +init_per_testcase(_, Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(300)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_, Config) -> + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +all(suite) -> [wall_clock, runtime, reductions, reductions_big, run_queue, + garbage_collection, io, badarg]. + + +%%% Testing statistics(wall_clock). + +wall_clock(suite) -> [wall_clock_zero_diff, wall_clock_update]. + + +wall_clock_zero_diff(doc) -> + "Tests that the 'Wall clock since last call' element of the result " + "is zero when statistics(runtime) is called twice in succession."; +wall_clock_zero_diff(Config) when is_list(Config) -> + wall_clock_zero_diff1(16). + +wall_clock_zero_diff1(N) when N > 0 -> + ?line {Time, _} = statistics(wall_clock), + ?line case statistics(wall_clock) of + {Time, 0} -> ok; + _ -> wall_clock_zero_diff1(N-1) + end; +wall_clock_zero_diff1(0) -> + ?line test_server:fail("Difference never zero."). + +wall_clock_update(doc) -> + "Test that the time differences returned by two calls to " + "statistics(wall_clock) are compatible, and are within a small number " + "of ms of the amount of real time we waited for."; +wall_clock_update(Config) when is_list(Config) -> + wall_clock_update1(6). + +wall_clock_update1(N) when N > 0 -> + ?line {T1_wc_time, _} = statistics(wall_clock), + ?line receive after 1000 -> ok end, + ?line {T2_wc_time, Wc_Diff} = statistics(wall_clock), + + ?line Wc_Diff = T2_wc_time - T1_wc_time, + ?line test_server:format("Wall clock diff = ~p; should be = 1000..1040~n", + [Wc_Diff]), + case ?t:is_debug() of + false -> + ?line true = Wc_Diff =< 1040; + true -> + ?line true = Wc_Diff =< 2000 %Be more tolerant in debug-compiled emulator. + end, + ?line true = Wc_Diff >= 1000, + wall_clock_update1(N-1); +wall_clock_update1(0) -> + ok. + + +%%% Test statistics(runtime). + +runtime(suite) -> [runtime_zero_diff, runtime_zero_update, runtime_update, + runtime_diff]. + +runtime_zero_diff(doc) -> + "Tests that the difference between the times returned from two consectuitive " + "calls to statistics(runtime) is zero."; +runtime_zero_diff(Config) when is_list(Config) -> + ?line runtime_zero_diff1(16). + +runtime_zero_diff1(N) when N > 0 -> + ?line {T1, _} = statistics(runtime), + ?line case statistics(runtime) of + {T1, 0} -> ok; + _ -> runtime_zero_diff1(N-1) + end; +runtime_zero_diff1(0) -> + ?line test_server:fail("statistics(runtime) never returned zero difference"). + +runtime_zero_update(doc) -> + "Test that the time differences returned by two calls to " + "statistics(runtime) several seconds apart is zero."; +runtime_zero_update(Config) when is_list(Config) -> + case ?t:is_debug() of + false -> ?line runtime_zero_update1(6); + true -> {skip,"Unreliable in DEBUG build"} + end. + +runtime_zero_update1(N) when N > 0 -> + ?line {T1, _} = statistics(runtime), + ?line receive after 7000 -> ok end, + ?line case statistics(runtime) of + {T, Td} when Td =< 80 -> + test_server:format("ok, Runtime before: {~p, _} after: {~p, ~p}", + [T1, T, Td]), + ok; + {T, R} -> + test_server:format("nok, Runtime before: {~p, _} after: {~p, ~p}", + [T1, T, R]), + runtime_zero_update1(N-1) + end; +runtime_zero_update1(0) -> + ?line test_server:fail("statistics(runtime) never returned zero difference"). + +runtime_update(doc) -> + "Test that the statistics(runtime) returns a substanstially updated difference " + "after running a process that takes all CPU power of the Erlang process " + "for a second."; +runtime_update(Config) when is_list(Config) -> + case ?t:is_cover() of + false -> + ?line process_flag(priority, high), + ?line test_server:m_out_of_n(1, 10, fun runtime_update/0); + true -> + {skip,"Cover-compiled"} + end. + +runtime_update() -> + ?line {T1,_} = statistics(runtime), + ?line spawn_link(fun cpu_heavy/0), + receive after 1000 -> ok end, + ?line {T2,Diff} = statistics(runtime), + ?line Delta = abs(Diff-1000), + ?line test_server:format("T1 = ~p, T2 = ~p, Diff = ~p, abs(Diff-1000) = ~p", + [T1,T2,Diff,Delta]), + ?line if + abs(Diff-1000) =:= Delta, Delta =< 100 -> + ok + end. + +cpu_heavy() -> + cpu_heavy(). + +runtime_diff(doc) -> + "Test that the difference between two consecutive absolute runtimes is " + "equal to the last relative runtime. The loop runs a lot of times since " + "the bug which this test case tests for showed up only rarely."; +runtime_diff(Config) when is_list(Config) -> + runtime_diff1(1000). + +runtime_diff1(N) when N > 0 -> + ?line {T1_wc_time, _} = statistics(runtime), + ?line do_much(), + ?line {T2_wc_time, Wc_Diff} = statistics(runtime), + ?line Wc_Diff = T2_wc_time - T1_wc_time, + runtime_diff1(N-1); +runtime_diff1(0) -> + ok. + +%%% do_much(100000) takes about 760 ms on boromir. +%%% do_much(1000) takes about 8 ms on boromir. + +do_much() -> + do_much(1000). + +do_much(0) -> + ok; +do_much(N) -> + _ = 4784728478274827 * 72874284728472, + do_much(N-1). + + +reductions(doc) -> + "Test that statistics(reductions) is callable, and that " + "Total_Reductions and Reductions_Since_Last_Call make sense. " + "(This to fail on pre-R3A version of JAM."; +reductions(Config) when is_list(Config) -> + {Reductions, _} = statistics(reductions), + + %% Each loop of reductions/2 takes 4 reductions + that the garbage built + %% outside the heap in the BIF calls will bump the reductions. + %% 300 * 4 is more than CONTEXT_REDS (1000). Thus, there will be one or + %% more context switches. + + reductions(300, Reductions). + +reductions(N, Previous) when N > 0 -> + ?line {Reductions, Diff} = statistics(reductions), + ?line build_some_garbage(), + ?line if Reductions > 0 -> ok end, + ?line if Diff >= 0 -> ok end, + io:format("Previous = ~p, Reductions = ~p, Diff = ~p, DiffShouldBe = ~p", + [Previous, Reductions, Diff, Reductions-Previous]), + ?line if Reductions == Previous+Diff -> reductions(N-1, Reductions) end; +reductions(0, _) -> + ok. + +build_some_garbage() -> + %% This will build garbage outside the process heap, which will cause + %% a garbage collection in the scheduler. + processes(). + +reductions_big(doc) -> + "Test that the number of reductions can be returned as a big number."; +reductions_big(Config) when is_list(Config) -> + ?line reductions_big_loop(), + ok. + +reductions_big_loop() -> + erlang:yield(), + case statistics(reductions) of + {Red, Diff} when Red >= 16#7ffFFFF -> + ok = io:format("Reductions = ~w, Diff = ~w", [Red, Diff]); + _ -> + reductions_big_loop() + end. + + +%%% Tests of statistics(run_queue). + +run_queue(suite) -> [run_queue_one]. + +run_queue_one(doc) -> + "Tests that statistics(run_queue) returns 1 if we start a " + "CPU-bound process."; +run_queue_one(Config) when is_list(Config) -> + ?line MS = erlang:system_flag(multi_scheduling, block), + ?line run_queue_one_test(Config), + ?line erlang:system_flag(multi_scheduling, unblock), + case MS of + blocked -> + {comment, + "Multi-scheduling blocked during test. This test-case " + "was not written to work with multiple schedulers."}; + _ -> ok + end. + + +run_queue_one_test(Config) when is_list(Config) -> + ?line Hog = spawn_link(?MODULE, hog, [self()]), + ?line receive + hog_started -> + Hog ! go + end, + ?line receive after 100 -> ok end, % Give hog a head start. + ?line case statistics(run_queue) of + N when N >= 1 -> ok; + Other -> ?line ?t:fail({unexpected,Other}) + end, + ok. + +%% CPU-bound process, going at low priority. It will always be ready +%% to run. + +hog(Pid) -> + ?line process_flag(priority, low), + ?line Pid ! hog_started, + ?line receive + go -> hog_iter(0) + end. + +hog_iter(N) when N > 0 -> + ?line hog_iter(N-1); +hog_iter(0) -> + ?line hog_iter(10000). + + +garbage_collection(doc) -> + "Tests that statistics(garbage_collection) is callable. " + "It is not clear how to test anything more."; +garbage_collection(Config) when is_list(Config) -> + ?line Bin = list_to_binary(lists:duplicate(19999, 42)), + ?line case statistics(garbage_collection) of + {Gcs0,R,0} when is_integer(Gcs0), is_integer(R) -> + ?line io:format("Reclaimed: ~p", [R]), + ?line Gcs = garbage_collection_1(Gcs0, Bin), + ?line io:format("Reclaimed: ~p", + [element(2, statistics(garbage_collection))]), + {comment,integer_to_list(Gcs-Gcs0)++" GCs"} + end. + +garbage_collection_1(Gcs0, Bin) -> + case statistics(garbage_collection) of + {Gcs,Reclaimed,0} when Gcs >= Gcs0 -> + if + Reclaimed > 16#7ffffff -> + Gcs; + true -> + _ = binary_to_list(Bin), + erlang:garbage_collect(), + garbage_collection_1(Gcs, Bin) + end + end. + +io(doc) -> + "Tests that statistics(io) is callable. " + "This could be improved to test something more."; +io(Config) when is_list(Config) -> + ?line case statistics(io) of + {{input,In},{output,Out}} when is_integer(In), is_integer(Out) -> ok + end. + +badarg(doc) -> + "Tests that some illegal arguments to statistics fails."; +badarg(Config) when is_list(Config) -> + ?line case catch statistics(1) of + {'EXIT', {badarg, _}} -> ok + end, + ?line case catch statistics(bad_atom) of + {'EXIT', {badarg, _}} -> ok + end. diff --git a/erts/emulator/test/suite_release.exclude b/erts/emulator/test/suite_release.exclude new file mode 100644 index 0000000000..74fdcc9653 --- /dev/null +++ b/erts/emulator/test/suite_release.exclude @@ -0,0 +1,6 @@ +driver_SUITE.erl +driver_SUITE_data +port_SUITE.erl +port_SUITE_data +fun_r7_SUITE.erl +node_container_SUITE.erl diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl new file mode 100644 index 0000000000..2c7124839a --- /dev/null +++ b/erts/emulator/test/system_info_SUITE.erl @@ -0,0 +1,142 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + + +%%%------------------------------------------------------------------- +%%% File : system_info_SUITE.erl +%%% Author : Rickard Green <[email protected]> +%%% Description : Misc tests of erlang:system_info/1 +%%% +%%% Created : 15 Jul 2005 by Rickard Green <[email protected]> +%%%------------------------------------------------------------------- +-module(system_info_SUITE). +-author('[email protected]'). + +%-define(line_trace, 1). + +-include("test_server.hrl"). + +%-compile(export_all). +-export([all/1, init_per_testcase/2, fin_per_testcase/2]). + +-export([process_count/1, system_version/1, misc_smoke_tests/1]). + +-define(DEFAULT_TIMEOUT, ?t:minutes(2)). + +all(doc) -> []; +all(suite) -> [process_count, system_version, misc_smoke_tests]. + +init_per_testcase(_Case, Config) when is_list(Config) -> + Dog = ?t:timetrap(?DEFAULT_TIMEOUT), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +%%% +%%% The test cases ------------------------------------------------------------- +%%% + +process_count(doc) -> []; +process_count(suite) -> []; +process_count(Config) when is_list(Config) -> + case catch erlang:system_info(modified_timing_level) of + Level when is_integer(Level) -> + {skipped, + "Modified timing (level " ++ integer_to_list(Level) + ++ ") is enabled. spawn() is too slow for this " + " test when modified timing is enabled."}; + _ -> + process_count_test() + end. + +process_count_test() -> + ?line OldPrio = process_flag(priority, max), + ?line check_procs(10), + ?line check_procs(11234), + ?line check_procs(57), + ?line check_procs(1030), + ?line check_procs(687), + ?line check_procs(7923), + ?line check_procs(5302), + ?line check_procs(12456), + ?line check_procs(14), + ?line check_procs(1125), + ?line check_procs(236), + ?line check_procs(125), + ?line check_procs(2346), + ?line process_flag(priority, OldPrio), + ?line ok. + + +check_procs(N) -> + ?line CP = length(processes()), + ?line Procs = start_procs(N), + ?line check_pc(CP+N), + ?line stop_procs(Procs), + ?line check_pc(CP). + +check_pc(E) -> + ?line P = length(processes()), + ?line SI = erlang:system_info(process_count), + ?line ?t:format("E=~p; P=~p; SI=~p~n", [E, P, SI]), + ?line E = P, + ?line P = SI. + +start_procs(N) -> + lists:map(fun (_) -> + P = spawn_opt(fun () -> + receive after infinity -> bye end + end, + [{priority, max}]), + {P, erlang:monitor(process, P)} + end, + lists:seq(1, N)). + +stop_procs(PMs) -> + lists:foreach(fun ({P, _}) -> + exit(P, boom) + end, PMs), + lists:foreach(fun ({P, M}) -> + receive {'DOWN', M, process, P, boom} -> ok end + end, PMs). + + +system_version(doc) -> []; +system_version(suite) -> []; +system_version(Config) when is_list(Config) -> + ?line {comment, erlang:system_info(system_version)}. + +misc_smoke_tests(doc) -> []; +misc_smoke_tests(suite) -> []; +misc_smoke_tests(Config) when is_list(Config) -> + ?line true = is_binary(erlang:system_info(info)), + ?line true = is_binary(erlang:system_info(procs)), + ?line true = is_binary(erlang:system_info(loaded)), + ?line true = is_binary(erlang:system_info(dist)), + ?line ok. + + + + + + + diff --git a/erts/emulator/test/system_profile_SUITE.erl b/erts/emulator/test/system_profile_SUITE.erl new file mode 100644 index 0000000000..7b0d6d19fe --- /dev/null +++ b/erts/emulator/test/system_profile_SUITE.erl @@ -0,0 +1,474 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + + +%%% Purpose : Tests system_profile BIF + +-module(system_profile_SUITE). + +-export([all/1, + system_profile_on_and_off/1, + runnable_procs/1, + runnable_ports/1, + scheduler/1 + ]). + +-export([init_per_testcase/2, fin_per_testcase/2]). + +-export([profiler_process/1, ring_loop/1, port_echo_start/0, list_load/0, run_load/2]). + +-include("test_server.hrl"). + +-define(default_timeout, ?t:minutes(1)). + +init_per_testcase(_Case, Config) -> + ?line Dog=?t:timetrap(?default_timeout), + [{watchdog, Dog}|Config]. +fin_per_testcase(_Case, Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +all(suite) -> + %% Test specification on test suite level + [system_profile_on_and_off, + runnable_procs, + runnable_ports, + scheduler]. + +%% No specification clause needed for an init function in a conf case!!! + +%% Test switching system_profiling on and off. +system_profile_on_and_off(suite) -> + []; +system_profile_on_and_off(doc) -> + ["Tests switching system_profiling on and off."]; +system_profile_on_and_off(Config) when is_list(Config) -> + ?line Pid = start_profiler_process(), + + % Test runnable_ports on and off + ?line undefined = erlang:system_profile(Pid, [runnable_ports]), + ?line {Pid, [runnable_ports]} = erlang:system_profile(), + ?line {Pid, [runnable_ports]} = erlang:system_profile(undefined, []), + + % Test runnable_procs on and off + ?line undefined = erlang:system_profile(Pid, [runnable_procs]), + ?line {Pid, [runnable_procs]} = erlang:system_profile(), + ?line {Pid, [runnable_procs]} = erlang:system_profile(undefined, []), + + % Test scheduler on and off + ?line undefined = erlang:system_profile(Pid, [scheduler]), + ?line {Pid, [scheduler]} = erlang:system_profile(), + ?line {Pid, [scheduler]} = erlang:system_profile(undefined, []), + + % Test combined runnable_ports, runnable_procs, scheduler; on and off + ?line undefined = erlang:system_profile(Pid, [scheduler, runnable_procs, runnable_ports]), + ?line {Pid, [scheduler,runnable_procs,runnable_ports]} = erlang:system_profile(), + ?line {Pid, [scheduler,runnable_procs,runnable_ports]} = erlang:system_profile(undefined, []), + + % Test turned off and kill process + ?line undefined = erlang:system_profile(), + ?line exit(Pid,kill), + ok. + +%% Test runnable_procs + +runnable_procs(suite) -> + []; +runnable_procs(doc) -> + ["Tests system_profiling with runnable_procs."]; +runnable_procs(Config) when is_list(Config) -> + ?line Pid = start_profiler_process(), + % start a ring of processes + % FIXME: Set #laps and #nodes in config file + Nodes = 10, + Laps = 10, + ?line Master = ring(Nodes), + ?line undefined = erlang:system_profile(Pid, [runnable_procs]), + % loop a message + ?line ok = ring_message(Master, message, Laps), + ?line Events = get_profiler_events(), + ?line kill_em_all = kill_ring(Master), + ?line erlang:system_profile(undefined, []), + put(master, Master), + put(laps, Laps), + ?line true = has_runnable_event(Events), + Pids = sort_events_by_pid(Events), + ?line ok = check_events(Pids), + erase(), + ?line exit(Pid,kill), + ok. + +runnable_ports(suite) -> + []; +runnable_ports(doc) -> + ["Tests system_profiling with runnable_port."]; +runnable_ports(Config) when is_list(Config) -> + ?line Pid = start_profiler_process(), + ?line undefined = erlang:system_profile(Pid, [runnable_ports]), + ?line EchoPid = echo(Config), + % FIXME: Set config to number_of_echos + Laps = 10, + put(laps, Laps), + ?line ok = echo_message(EchoPid, Laps, message), + ?line Events = get_profiler_events(), + ?line kill_em_all = kill_echo(EchoPid), + ?line erlang:system_profile(undefined, []), + ?line true = has_runnable_event(Events), + Pids = sort_events_by_pid(Events), + ?line ok = check_events(Pids), + erase(), + ?line exit(Pid,kill), + ok. + +scheduler(suite) -> + []; +scheduler(doc) -> + ["Tests system_profiling with scheduler."]; +scheduler(Config) when is_list(Config) -> + case {erlang:system_info(smp_support), erlang:system_info(schedulers_online)} of + {false,_} -> ?line {skipped, "No need for scheduler test when smp support is disabled."}; + {_, 1} -> ?line {skipped, "No need for scheduler test when only one scheduler online."}; + _ -> + Nodes = 10, + ?line ok = check_block_system(Nodes), + ?line ok = check_multi_scheduling_block(Nodes), + ok + end. + +%%% Check scheduler profiling + +check_multi_scheduling_block(Nodes) -> + ?line Pid = start_profiler_process(), + ?line undefined = erlang:system_profile(Pid, [scheduler]), + ?line {ok, Supervisor} = start_load(Nodes), + ?line erlang:system_flag(multi_scheduling, block), + ?line erlang:system_flag(multi_scheduling, unblock), + ?line {Pid, [scheduler]} = erlang:system_profile(undefined, []), + ?line Events = get_profiler_events(), + ?line true = has_scheduler_event(Events), + stop_load(Supervisor), + ?line exit(Pid,kill), + erase(), + ok. + +check_block_system(Nodes) -> + ?line Dummy = spawn(?MODULE, profiler_process, [[]]), + ?line Pid = start_profiler_process(), + ?line undefined = erlang:system_profile(Pid, [scheduler]), + ?line {ok, Supervisor} = start_load(Nodes), + % FIXME: remove wait !! + wait(300), + ?line undefined = erlang:system_monitor(Dummy, [busy_port]), + ?line {Dummy, [busy_port]} = erlang:system_monitor(undefined, []), + ?line {Pid, [scheduler]} = erlang:system_profile(undefined, []), + ?line Events = get_profiler_events(), + ?line true = has_scheduler_event(Events), + stop_load(Supervisor), + ?line exit(Pid,kill), + ?line exit(Dummy,kill), + erase(), + ok. + +%%% Check events + +check_events([]) -> ok; +check_events([Pid | Pids]) -> + Master = get(master), + Laps = get(laps), + CheckPids = get(pids), + {Events, N} = get_pid_events(Pid), + ?line ok = check_event_flow(Events), + ?line ok = check_event_ts(Events), + IsMember = lists:member(Pid, CheckPids), + case Pid of + Master -> + io:format("Expected ~p and got ~p profile events from ~p: ok~n", [Laps*2+2, N, Pid]), + ?line N = Laps*2 + 2, + check_events(Pids); + Pid when IsMember == true -> + io:format("Expected ~p and got ~p profile events from ~p: ok~n", [Laps*2, N, Pid]), + ?line N = Laps*2, + check_events(Pids); + Pid -> + check_events(Pids) + end. + +%% timestamp consistency check for descending timestamps + +check_event_ts(Events) -> + check_event_ts(Events, undefined). +check_event_ts([], _) -> ok; +check_event_ts([Event | Events], undefined) -> + check_event_ts(Events, Event); +check_event_ts([{Pid, _, _, TS1}=Event | Events], {Pid,_,_,TS0}) -> + Time = timer:now_diff(TS1, TS0), + if + Time < 0.0 -> timestamp_error; + true -> check_event_ts(Events, Event) + end. + +%% consistency check for active vs. inactive activity (runnable) + +check_event_flow(Events) -> + check_event_flow(Events, undefined). +check_event_flow([], _) -> ok; +check_event_flow([Event | PidEvents], undefined) -> + check_event_flow(PidEvents, Event); +check_event_flow([{Pid,Act,_,_}=Event | Events], PrevEvent) -> + case PrevEvent of + {Pid, Act, _MFA, _TS} -> consistency_error; + _ -> check_event_flow(Events, Event) + end. + + + +get_pid_events(Pid) -> + Events = get({pid_events, Pid}), + {Events, length(Events)}. + +sort_events_by_pid(Events) -> + sort_events_by_pid(lists:reverse(Events), []). +sort_events_by_pid([], Pids) -> Pids; +sort_events_by_pid([Event | Events],Pids) -> + case Event of + {profile,Pid,Act,MFA,TS} -> + case get({pid_events, Pid}) of + undefined -> + put({pid_events, Pid}, [{Pid,Act,MFA,TS}]), + sort_events_by_pid(Events, [Pid | Pids]); + PidEvents -> + put({pid_events, Pid}, [{Pid,Act,MFA,TS}|PidEvents]), + sort_events_by_pid(Events, Pids) + end + end. + + +%%% +%% Process ring +%%% + +%% API + +% Returns master pid +ring(N) -> + Pids = build_ring(N, []), + put(pids, Pids), + setup_ring(Pids). + +ring_message(Master, Message, Laps) -> + Master ! {message, Master, Laps, Message}, + receive + {laps_complete, Master} -> ok + end. + +kill_ring(Master) -> Master ! kill_em_all. + +%% Process ring helpers + +build_ring(0, Pids) -> Pids; +build_ring(N, Pids) -> + build_ring(N - 1, [spawn_link(?MODULE, ring_loop, [undefined]) | Pids]). + +setup_ring([Master | Relayers]) -> + % Relayers may not include the master pid + Master ! {setup_ring, Relayers, self()}, + receive + {setup_complete, Master} -> Master + end. + +ring_loop(RelayTo) -> + receive + kill_em_all -> + RelayTo ! kill_em_all; + {setup_ring, [Pid | Pids], Supervisor} -> + put(supervisor, Supervisor), + Pid ! {relay_to, Pids, self()}, + ring_loop(Pid); + {setup_complete, _} -> + get(supervisor) ! {setup_complete, self()}, + ring_loop(RelayTo); + {relay_to, [], Master} -> + Master ! {setup_complete, self()}, + ring_loop(Master); + {relay_to, [Pid | Pids], Master} -> + Pid ! {relay_to, Pids, Master}, + ring_loop(Pid); + {message, Master, Lap, Msg}=Message -> + case {self(), Lap} of + {Master, 0} -> + get(supervisor) ! {laps_complete, self()}, + ring_loop(RelayTo); + {Master, Lap} -> + RelayTo ! {message, Master, Lap - 1, Msg}, + ring_loop(RelayTo); + _ -> + RelayTo ! Message, + ring_loop(RelayTo) + end + end. + +%%% +%% Echo driver +%%% + +%% API + +echo(Config) -> + Path = ?config(data_dir, Config), + erl_ddll:load_driver(Path, echo_drv), + Pid = spawn_link(?MODULE, port_echo_start, []), + Pid ! {self(), get_ports}, + receive + {port, Port} -> + put(pids, [Port]), + put(master, Port), + Pid + end. + +echo_message(Pid, N, Msg) -> + Pid ! {start_echo, self(), N, Msg}, + receive + {echo_complete, Pid} -> ok + end. + +kill_echo(Pid) -> Pid ! kill_em_all. + + +%% Echo driver helpers +port_echo_start() -> + Port = open_port({spawn,echo_drv}, [eof,binary]), + receive + {Pid, get_ports} -> + Pid ! {port, Port}, + port_echo_loop(Port) + end. + +port_echo_loop(Port) -> + receive + {start_echo, Pid, Echos, Msg} -> + port_command(Port, term_to_binary({Pid, Echos, Msg})), + port_echo_loop(Port); + {Port, {data, Data}} -> + {Pid, Echos, Msg} = binary_to_term(Data), + case Echos of + 0 -> + Pid ! {echo_complete, self()}, + port_echo_loop(Port); + Echos -> + port_command(Port, term_to_binary({Pid, Echos - 1, Msg})), + port_echo_loop(Port) + end; + kill_em_all -> + port_close(Port), + ok + end. + + + +%%% +%% Helpers +%%% + +start_load(N) -> + Pid = spawn_link(?MODULE, run_load, [N, []]), + {ok, Pid}. + + +stop_load(Supervisor) -> + erlang:unlink(Supervisor), + exit(Supervisor, kill). + +run_load(0, _Pids) -> + receive + % wait for an exit signal or a message then kill + % all associated processes. + _ -> exit(annihilated) + end; +run_load(N, Pids) -> + Pid = spawn_link(?MODULE, list_load, []), + run_load(N - 1, [Pid | Pids]). + +list_load() -> + ok = case math:sin(random:uniform(32451)) of + A when is_float(A) -> ok; + _ -> ok + end, + list_load(). + + +has_scheduler_event(Events) -> + lists:any( + fun (Pred) -> + case Pred of + {profile, scheduler, _ID, _Activity, _NR, _TS} -> true; + _ -> false + end + end, Events). + +has_runnable_event(Events) -> + lists:any( + fun (Pred) -> + case Pred of + {profile, _Pid, _Activity, _MFA, _TS} -> true; + _ -> false + end + end, Events). + +wait(Time) -> receive after Time -> ok end. + +%%% +%% Receivers +%%% + +%% Process receiver + + +get_profiler_events() -> + Pid = get(profiler), + Pid ! {self(), get_events}, + receive + Events -> Events + end. + +start_profiler_process() -> + Pid = spawn(?MODULE, profiler_process, [[]]), + put(profiler, Pid), + Pid. + +profiler_process(Events) -> + receive + {Pid, get_events} -> + Ref = erlang:trace_delivered(all), + profiler_process_followup(Pid, Events, Ref); + Event -> + profiler_process([Event | Events]) + end. + +profiler_process_followup(Pid, Events, Ref) -> + receive + {trace_delivered,all,Ref} -> + Pid ! lists:reverse(Events); + Event -> + profiler_process_followup(Pid, [Event | Events], Ref) + end. + +%% Port receiver + + diff --git a/erts/emulator/test/system_profile_SUITE_data/Makefile.src b/erts/emulator/test/system_profile_SUITE_data/Makefile.src new file mode 100644 index 0000000000..c1bf142ccf --- /dev/null +++ b/erts/emulator/test/system_profile_SUITE_data/Makefile.src @@ -0,0 +1,3 @@ +all: echo_drv@dll@ + +@SHLIB_RULES@ diff --git a/erts/emulator/test/system_profile_SUITE_data/echo_drv.c b/erts/emulator/test/system_profile_SUITE_data/echo_drv.c new file mode 100644 index 0000000000..d968ff06f9 --- /dev/null +++ b/erts/emulator/test/system_profile_SUITE_data/echo_drv.c @@ -0,0 +1,66 @@ +#include <stdio.h> +#include "erl_driver.h" + +typedef struct _erl_drv_data { + ErlDrvPort erlang_port; +} EchoDrvData; + +static EchoDrvData echo_drv_data, *echo_drv_data_p; + +static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command); +static void echo_drv_stop(EchoDrvData *data_p); +static void echo_drv_output(EchoDrvData *data_p, char *buf, int len); +static void echo_drv_finish(void); +static int echo_drv_control(EchoDrvData *data_p, unsigned int command, + char *buf, int len, + char **rbuf, int rlen); + +static ErlDrvEntry echo_drv_entry = { + NULL, /* init */ + echo_drv_start, + echo_drv_stop, + echo_drv_output, + NULL, /* ready_input */ + NULL, /* ready_output */ + "echo_drv", + echo_drv_finish, + NULL, /* handle */ + echo_drv_control, + NULL, /* timeout */ + NULL, /* outputv */ + NULL /* ready_async */ +}; + +DRIVER_INIT(echo_drv) +{ + echo_drv_data_p = NULL; + return &echo_drv_entry; +} + +static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command) +{ + if (echo_drv_data_p != NULL) { + return ERL_DRV_ERROR_GENERAL; + } + echo_drv_data_p = &echo_drv_data; + echo_drv_data_p->erlang_port = port; + return echo_drv_data_p; +} + +static void echo_drv_stop(EchoDrvData *data_p) { + echo_drv_data_p = NULL; +} + +static void echo_drv_output(EchoDrvData *data_p, char *buf, int len) { + driver_output(data_p->erlang_port, buf, len); +} + +static void echo_drv_finish() { + echo_drv_data_p = NULL; +} + +static int echo_drv_control(EchoDrvData *data_p, unsigned int command, + char *buf, int len, + char **rbuf, int rlen) { + return 0; +} diff --git a/erts/emulator/test/time_SUITE.erl b/erts/emulator/test/time_SUITE.erl new file mode 100644 index 0000000000..2ad1f0d201 --- /dev/null +++ b/erts/emulator/test/time_SUITE.erl @@ -0,0 +1,439 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(time_SUITE). + +%% "Time is on my side." -- The Rolling Stones + +%% Tests the BIFs: +%% erlang:localtime_to_universaltime/1 +%% erlang:universaltime_to_localtime/1 +%% date/0 +%% time/0 +%% now/0 +%% + +-export([all/1, univ_to_local/1, local_to_univ/1, + bad_univ_to_local/1, bad_local_to_univ/1, + consistency/1, + now/1, now_unique/1, now_update/1, timestamp/1]). + +-include("test_server.hrl"). + +-export([linear_time/1]). + +%% The following defines the timezone in which the test is run. +%% It is interpreted as the number of hours to be added to UTC +%% to obtain the local time. The number will be positive east +%% of Greenwhich, negative west of Greenwhich. +%% +%% Allowable range is -12 through 11. + +-define(timezone, 1). + +%% Similarly to timezone, but the difference when Daylight Saving Time +%% is in use. [Same range.] + +-define(dst_timezone, 2). + +all(suite) -> [univ_to_local, local_to_univ, + bad_univ_to_local, bad_local_to_univ, consistency, now, timestamp]. + + +%% Tests conversion from univeral to local time. + +univ_to_local(Config) when is_list(Config) -> + ?line test_univ_to_local(test_data()). + +test_univ_to_local([{Utc, Local}|Rest]) -> + ?line io:format("Testing ~p => ~p~n", [Local, Utc]), + ?line Local = erlang:universaltime_to_localtime(Utc), + ?line test_univ_to_local(Rest); +test_univ_to_local([]) -> + ok. + +%% Tests conversion from local to universal time. + +local_to_univ(Config) when is_list(Config) -> + ?line test_local_to_univ(test_data()). + +test_local_to_univ([{Utc, Local}|Rest]) -> + ?line io:format("Testing ~p => ~p~n", [Utc, Local]), + ?line Utc = erlang:localtime_to_universaltime(Local), + ?line test_local_to_univ(Rest); +test_local_to_univ([]) -> + ok. + +%% Test bad arguments to erlang:universaltime_to_localtime; should +%% generate a badarg. + +bad_univ_to_local(Config) when is_list(Config) -> + ?line bad_test_univ_to_local(bad_dates()). + +bad_test_univ_to_local([Utc|Rest]) -> + ?line io:format("Testing ~p~n", [Utc]), + ?line case catch erlang:universaltime_to_localtime(Utc) of + {'EXIT', {badarg, _}} -> bad_test_univ_to_local(Rest) + end; +bad_test_univ_to_local([]) -> + ok. + +%% Test bad arguments to erlang:localtime_to_universaltime/1; should +%% generate a badarg. + +bad_local_to_univ(Config) when is_list(Config) -> + ?line bad_test_local_to_univ(bad_dates()). + +bad_test_local_to_univ([Local|Rest]) -> + ?line io:format("Testing ~p~n", [Local]), + ?line case catch erlang:localtime_to_universaltime(Local) of + {'EXIT', {badarg, _}} -> bad_test_local_to_univ(Rest) + end; +bad_test_local_to_univ([]) -> + ok. + +%% Test that the the different time functions return +%% consistent results. (See the test case for assumptions +%% and limitations.) +consistency(Config) when is_list(Config) -> + %% Test the following equations: + %% date() & time() == erlang:localtime() + %% erlang:universaltime() + timezone == erlang:localtime() + %% + %% Assumptions: + %% Middle-European time zone, EU rules for daylight-saving time. + %% + %% Limitations: + %% Localtime and universaltime must be in the same month. + %% Daylight-saving calculations are incorrect from the last + %% Sunday of March and October to the end of the month. + + ?line ok = compare_date_time_and_localtime(16), + ?line ok = compare_local_and_universal(16). + +compare_date_time_and_localtime(Times) when Times > 0 -> + ?line {Year, Mon, Day} = date(), + ?line {Hour, Min, Sec} = time(), + ?line case erlang:localtime() of + {{Year, Mon, Day}, {Hour, Min, Sec}} -> ok; + _ -> compare_date_time_and_localtime(Times-1) + end; +compare_date_time_and_localtime(0) -> + error. + +compare_local_and_universal(Times) when Times > 0 -> + case compare(erlang:universaltime(), erlang:localtime()) of + true -> ok; + false -> compare_local_and_universal(Times-1) + end; +compare_local_and_universal(0) -> + error. + +compare(Utc0, Local) -> + io:format("local = ~p, utc = ~p", [Local, Utc0]), + Utc = linear_time(Utc0)+effective_timezone(Utc0)*3600, + case linear_time(Local) of + Utc -> true; + Other -> + io:format("Failed: local = ~p, utc = ~p~n", + [Other, Utc]), + false + end. + +%% This function converts a date and time to a linear time. +%% Two linear times can be subtracted to give their difference +%% in seconds. +%% +%% XXX Limitations: The length of months and leap years are not +%% taken into account; thus a comparision of dates is only +%% valid if they are in the SAME month. + +linear_time({{Year, Mon, Day}, {Hour, Min, Sec}}) -> + 86400*(366*Year + 31*(Mon-1) + (Day-1)) + + 3600*Hour + 60*Min + Sec. + +%% This functions returns either the normal timezone or the +%% the DST timezone, depending on the given UTC time. +%% +%% XXX This function uses an approximation of the EU rule for +%% daylight saving time. This function will fail in the +%% following intervals: After the last Sunday in March upto +%% the end of March, and after the last Sunday in October +%% upto the end of October. + +effective_timezone(Time) -> + case os:type() of + {unix,_} -> + case os:cmd("date '+%Z'") of + "SAST"++_ -> + 2; + _ -> + effective_timezone1(Time) + end; + _ -> + effective_timezone1(Time) + end. + +effective_timezone1({{_Year,Mon,_Day}, _}) when Mon < 4 -> + ?timezone; +effective_timezone1({{_Year,Mon,_Day}, _}) when Mon > 10 -> + ?timezone; +effective_timezone1(_) -> + ?dst_timezone. + +%% Test (the bif) os:timestamp/0, which is something quite like, but not +%% similar to erlang:now... + +timestamp(suite) -> + []; +timestamp(doc) -> + ["Test that os:timestamp works."]; +timestamp(Config) when is_list(Config) -> + repeating_timestamp_check(100000). + +repeating_timestamp_check(0) -> + ok; +repeating_timestamp_check(N) -> + {A,B,C} = TS = os:timestamp(), + if + is_integer(A), + is_integer(B), + is_integer(C), + B < 1000000, + C < 1000000 -> + ok; + true -> + test_server:fail( + lists:flatten( + io_lib:format("Strange return from os:timestamp/0 ~w~n",[TS]))) + end, + %% I assume the now and timestamp should not differ more than 1 hour, + %% which is safe assuming the system has not had a large time-warp + %% during the testrun... + Secs = A*1000000+B+round(C/1000000), + {NA,NB,NC} = erlang:now(), + NSecs = NA*1000000+NB+round(NC/1000000), + case Secs - NSecs of + TooLarge when TooLarge > 3600 -> + test_server:fail( + lists:flatten( + io_lib:format("os:timestamp/0 is ~w s more than erlang:now/0", + [TooLarge]))); + TooSmall when TooSmall < -3600 -> + test_server:fail( + lists:flatten( + io_lib:format("os:timestamp/0 is ~w s less than erlang:now/0", + [-TooSmall]))); + _ -> + ok + end, + repeating_timestamp_check(N-1). + + +%% Test now/0. + +now(suite) -> [now_unique, now_update]. + +%% Tests that successive calls to now/0 returns different values. +%% Also returns a comment string with the median difference between +%% times (in microseconds). + +now_unique(Config) when is_list(Config) -> + ?line now_unique(1000, now(), []), + ?line fast_now_unique(100000, now()). + +now_unique(N, Previous, Result) when N > 0 -> + ?line case now() of + Previous -> + test_server:fail("now/0 returned the same value twice"); + New -> + now_unique(N-1, New, [New|Result]) + end; +now_unique(0, _, [Then|Rest]) -> + ?line now_calc_increment(Rest, microsecs(Then), []). + +now_calc_increment([Then|Rest], Previous, _Result) -> + ?line This = microsecs(Then), + ?line now_calc_increment(Rest, This, [Previous-This]); +now_calc_increment([], _, Differences) -> + {comment, "Median increment: " ++ integer_to_list(median(Differences))}. + +fast_now_unique(0, _) -> ok; +fast_now_unique(N, Then) -> + case now() of + Then -> + ?line ?t:fail("now/0 returned the same value twice"); + Now -> + fast_now_unique(N-1, Now) + end. + +median(Unsorted_List) -> + ?line Length = length(Unsorted_List), + ?line List = lists:sort(Unsorted_List), + ?line case Length rem 2 of + 0 -> % Even length. + [A, B] = lists:nthtail((Length div 2)-1, List), + (A+B)/2; + 1 -> % Odd list length. + lists:nth((Length div 2)+1, List) + end. + +microsecs({Mega_Secs, Secs, Microsecs}) -> + (Mega_Secs*1000000+Secs)*1000000+Microsecs. + +%% Test that the time differences returned by two calls to +%% now/0 one second apart is comparable to the difference of two +%% calls to erlang:localtime(). + +now_update(Config) when is_list(Config) -> + case ?t:is_debug() of + false -> ?line now_update1(10); + true -> {skip,"Unreliable in DEBUG build"} + end. + + +now_update1(N) when N > 0 -> + ?line T1_linear = linear_time(erlang:localtime()), + ?line T1_now = microsecs(now()), + + ?line receive after 1008 -> ok end, + + ?line T2_linear = linear_time(erlang:localtime()), + ?line T2_now = microsecs(now()), + + ?line Linear_Diff = (T2_linear-T1_linear)*1000000, + ?line Now_Diff = T2_now-T1_now, + test_server:format("Localtime diff = ~p; now() diff = ~p", + [Linear_Diff, Now_Diff]), + ?line case abs(Linear_Diff - Now_Diff) of + Abs_Delta when Abs_Delta =< 40000 -> ok; + _ -> now_update1(N-1) + end; +now_update1(0) -> + ?line test_server:fail(). + +%% Returns the test data: a list of {Utc, Local} tuples. + +test_data() -> + {TZ,DSTTZ} = + case os:type() of + {unix,_} -> + case os:cmd("date '+%Z'") of + "SAST"++_ -> + {2,2}; + _ -> + {?timezone,?dst_timezone} + end; + _ -> + {?timezone,?dst_timezone} + end, + ?line test_data(nondst_dates(), TZ) ++ + test_data(dst_dates(), DSTTZ) ++ + crossover_test_data(crossover_dates(), TZ). + + +%% test_data1() -> +%% ?line test_data(nondst_dates(), ?timezone) ++ +%% test_data(dst_dates(), ?dst_timezone) ++ +%% crossover_test_data(crossover_dates(), ?timezone). + +crossover_test_data([{Year, Month, Day}|Rest], TimeZone) when TimeZone > 0 -> + Hour = 23, + Min = 35, + Sec = 55, + ?line Utc = {{Year, Month, Day}, {Hour, Min, Sec}}, + ?line Local = {{Year, Month, Day+1}, {Hour+TimeZone-24, Min, Sec}}, + ?line [{Utc, Local}|crossover_test_data(Rest, TimeZone)]; +crossover_test_data([{Year, Month, Day}|Rest], TimeZone) when TimeZone < 0 -> + Hour = 0, + Min = 23, + Sec = 12, + ?line Utc = {{Year, Month, Day}, {Hour, Min, Sec}}, + ?line Local = {{Year, Month, Day-1}, {Hour+TimeZone+24, Min, Sec}}, + ?line [{Utc, Local}|crossover_test_data(Rest, TimeZone)]; +crossover_test_data([], _) -> + []. + +test_data([Date|Rest], TimeZone) -> + Hour = 12, + Min = 45, + Sec = 7, + ?line Utc = {Date, {Hour, Min, Sec}}, + ?line Local = {Date, {Hour+TimeZone, Min, Sec}}, + ?line [{Utc, Local}|test_data(Rest, TimeZone)]; +test_data([], _) -> + []. + +nondst_dates() -> + [{1996, 01, 30}, + {1997, 01, 30}, + {1998, 01, 30}, + {1999, 01, 30}, + {1996, 02, 29}, + {1997, 02, 28}, + {1998, 02, 28}, + {1999, 02, 28}, + {1996, 03, 2}, + {1997, 03, 2}, + {1998, 03, 2}, + {1999, 03, 2}]. + +dst_dates() -> + [{1996, 06, 1}, + {1997, 06, 2}, + {1998, 06, 3}, + {1999, 06, 4}]. + +%% The following dates should not be near the end or beginning of +%% a month, because they will be used to test when the dates are +%% different in UTC and local time. + +crossover_dates() -> + [{1996, 01, 25}, + {1997, 01, 25}, + {1998, 01, 25}, + {1999, 01, 25}, + {1996, 02, 27}, + {1997, 02, 27}, + {1998, 02, 27}, + {1999, 02, 27}]. + +bad_dates() -> + [{{1900, 7, 1}, {12, 0, 0}}, % Year + + {{1996, 0, 20}, {12, 0, 0}}, % Month + {{1996, 13, 20}, {12, 0, 0}}, + + {{1996, 1, 0}, {12, 0, 0}}, % Date + {{1996, 1, 32}, {12, 0, 0}}, + {{1996, 2, 30}, {12, 0, 0}}, + {{1997, 2, 29}, {12, 0, 0}}, + {{1998, 2, 29}, {12, 0, 0}}, + {{1999, 2, 29}, {12, 0, 0}}, + {{1996, 4, 31}, {12, 0, 0}}, + + {{1996, 4, 30}, {-1, 0, 0}}, % Hour + {{1996, 4, 30}, {25, 0, 0}}, + + {{1996, 4, 30}, {12,-1, 0}}, % Minute + {{1996, 4, 30}, {12, 60, 0}}, + + {{1996, 4, 30}, {12, 0, -1}}, % Sec + {{1996, 4, 30}, {12, 0, 60}}]. + diff --git a/erts/emulator/test/timer_bif_SUITE.erl b/erts/emulator/test/timer_bif_SUITE.erl new file mode 100644 index 0000000000..9ac5afcc45 --- /dev/null +++ b/erts/emulator/test/timer_bif_SUITE.erl @@ -0,0 +1,558 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(timer_bif_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2,end_per_suite/1]). +-export([start_timer_1/1, send_after_1/1, send_after_2/1, send_after_3/1, + cancel_timer_1/1, + start_timer_big/1, send_after_big/1, + start_timer_e/1, send_after_e/1, cancel_timer_e/1, + read_timer_trivial/1, read_timer/1, + cleanup/1, evil_timers/1, registered_process/1]). + +-include("test_server.hrl"). + +init_per_testcase(_Case, Config) -> + ?line Dog=test_server:timetrap(test_server:seconds(30)), + case catch erts_debug:get_internal_state(available_internal_state) of + true -> ok; + _ -> erts_debug:set_internal_state(available_internal_state, true) + end, + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +end_per_suite(_Config) -> + catch erts_debug:set_internal_state(available_internal_state, false). + +all(suite) -> + [start_timer_1, send_after_1, send_after_2, cancel_timer_1, + start_timer_e, send_after_e, cancel_timer_e, + start_timer_big, send_after_big, read_timer_trivial, read_timer, + cleanup, evil_timers, registered_process]. + +start_timer_1(doc) -> ["Basic start_timer/3 functionality"]; +start_timer_1(Config) when is_list(Config) -> + ?line Ref1 = erlang:start_timer(1000, self(), plopp), + ?line ok = get(1100, {timeout, Ref1, plopp}), + + ?line false = erlang:read_timer(Ref1), + ?line false = erlang:cancel_timer(Ref1), + ?line false = erlang:read_timer(Ref1), + + ?line Ref2 = erlang:start_timer(1000, self(), plapp), + ?line Left2 = erlang:cancel_timer(Ref2), + UpperLimit = case os:type() of + vxworks -> + %% The ticks of vxworks have a far lesser granularity + %% than what is expected in this testcase, in + %% fact the Left2 variable can get a little more than 1000... + 1100; + _ -> + 1000 + end, + ?line RetVal = case os:type() of + vxworks -> + {comment, "VxWorks behaves slightly unexpected, should be fixed,"}; + _ -> + ok + end, + ?line true = (Left2 > 900) and (Left2 =< UpperLimit), + ?line empty = get_msg(), + ?line false = erlang:cancel_timer(Ref2), + + ?line Ref3 = erlang:start_timer(1000, self(), plopp), + ?line no_message = get(900, {timeout, Ref3, plopp}), + + RetVal. + +send_after_1(doc) -> ["Basic send_after/3 functionality"]; +send_after_1(Config) when is_list(Config) -> + ?line Ref3 = erlang:send_after(1000, self(), plipp), + ?line ok = get(1500, plipp), + ?line false = erlang:read_timer(Ref3), + ok. + +start_timer_big(doc) -> ["Big timeouts for start_timer/3"]; +start_timer_big(Config) when is_list(Config) -> + ?line Big = 1 bsl 31, + ?line R = erlang:start_timer(Big, self(), hej), + ?line timer:sleep(200), + ?line Left = erlang:cancel_timer(R), + ?line case Big - Left of + Diff when Diff >= 200, Diff < 10000 -> + ok; + _Diff -> + test_server:fail({big, Big, Left}) + end, + ok. + +send_after_big(doc) -> ["Big timeouts for send_after/3"]; +send_after_big(Config) when is_list(Config) -> + ?line Big = 1 bsl 31, + ?line R = erlang:send_after(Big, self(), hej), + ?line timer:sleep(200), + ?line Left = erlang:cancel_timer(R), + ?line case Big - Left of + Diff when Diff >= 200, Diff < 10000 -> + ok; + _Diff -> + test_server:fail({big, Big, Left}) + end, + ok. + +send_after_2(doc) -> ["send_after/3: messages in the right order, kind version"]; +send_after_2(Config) when is_list(Config) -> + ?line _ = erlang:send_after(5000, self(), last), + ?line _ = erlang:send_after(0, self(), a0), + ?line _ = erlang:send_after(200, self(), a2), + ?line _ = erlang:send_after(100, self(), a1), + ?line _ = erlang:send_after(500, self(), a5), + ?line _ = erlang:send_after(300, self(), a3), + ?line _ = erlang:send_after(400, self(), a4), + ?line [a0,a1,a2,a3,a4,a5,last] = collect(last), + ok. + +send_after_3(doc) -> ["send_after/3: messages in the right order, worse than send_after_2"]; +send_after_3(Config) when is_list(Config) -> + case os:type() of + vxworks -> + {skipped, "VxWorks timer granularity and order is not working good, this is subject to change!"}; + _ -> + do_send_after_3() + end. + +do_send_after_3() -> + ?line _ = erlang:send_after(100, self(), b1), + ?line _ = erlang:send_after(101, self(), b2), + ?line _ = erlang:send_after(102, self(), b3), + ?line _ = erlang:send_after(103, self(), last), + ?line [b1, b2, b3, last] = collect(last), + +% This behaviour is not guaranteed: +% ?line _ = erlang:send_after(100, self(), c1), +% ?line _ = erlang:send_after(100, self(), c2), +% ?line _ = erlang:send_after(100, self(), c3), +% ?line _ = erlang:send_after(100, self(), last), +% ?line [c1, c2, c3, last] = collect(last), + + ok. + +cancel_timer_1(doc) -> ["Check trivial cancel_timer/1 behaviour"]; +cancel_timer_1(Config) when is_list(Config) -> + ?line false = erlang:cancel_timer(make_ref()), + + ok. + +start_timer_e(doc) -> ["Error cases for start_timer/3"]; +start_timer_e(Config) when is_list(Config) -> + ?line {'EXIT', _} = (catch erlang:start_timer(-4, self(), hej)), + ?line {'EXIT', _} = (catch erlang:start_timer(4728472847827482, + self(), hej)), + + ?line {'EXIT', _} = (catch erlang:start_timer(4.5, self(), hej)), + ?line {'EXIT', _} = (catch erlang:start_timer(a, self(), hej)), + + ?line Node = start_slave(), + ?line Pid = spawn(Node, timer, sleep, [10000]), + ?line {'EXIT', _} = (catch erlang:start_timer(1000, Pid, hej)), + ?line stop_slave(Node), + + + ok. + +send_after_e(doc) -> ["Error cases for send_after/3"]; +send_after_e(suite) -> []; +send_after_e(Config) when is_list(Config) -> + ?line {'EXIT', _} = (catch erlang:send_after(-4, self(), hej)), + ?line {'EXIT', _} = (catch erlang:send_after(4728472847827482, + self(), hej)), + + ?line {'EXIT', _} = (catch erlang:send_after(4.5, self(), hej)), + ?line {'EXIT', _} = (catch erlang:send_after(a, self(), hej)), + + ?line Node = start_slave(), + ?line Pid = spawn(Node, timer, sleep, [10000]), + ?line {'EXIT', _} = (catch erlang:send_after(1000, Pid, hej)), + ?line stop_slave(Node), + ok. + +cancel_timer_e(doc) -> ["Error cases for cancel_timer/1"]; +cancel_timer_e(suite) -> []; +cancel_timer_e(Config) when is_list(Config) -> + ?line {'EXIT', _} = (catch erlang:cancel_timer(1)), + ?line {'EXIT', _} = (catch erlang:cancel_timer(self())), + ?line {'EXIT', _} = (catch erlang:cancel_timer(a)), + ok. + +read_timer_trivial(doc) -> ["Trivial and error test cases for read_timer/1."]; +read_timer_trivial(suite) -> []; +read_timer_trivial(Config) when is_list(Config) -> + ?line false = erlang:read_timer(make_ref()), + ?line {'EXIT', _} = (catch erlang:read_timer(42)), + ?line {'EXIT', _} = (catch erlang:read_timer(423497834744444444457667444444)), + ?line {'EXIT', _} = (catch erlang:read_timer(self())), + ?line {'EXIT', _} = (catch erlang:read_timer(ab)), + ok. + +read_timer(doc) -> ["Test that read_timer/1 seems to return the correct values."]; +read_timer(suite) -> []; +read_timer(Config) when is_list(Config) -> + ?line Big = 1 bsl 31, + ?line R = erlang:send_after(Big, self(), hej_hopp), + + ?line receive after 200 -> ok end, % Delay and clear reductions. + ?line Left = erlang:read_timer(R), + ?line Left = erlang:cancel_timer(R), + ?line false = erlang:read_timer(R), + + ?line case Big - Left of + Diff when Diff >= 200, Diff < 10000 -> + ok; + _Diff -> + test_server:fail({big, Big, Left}) + end, + ok. + +cleanup(doc) -> []; +cleanup(suite) -> []; +cleanup(Config) when is_list(Config) -> + ?line Mem = mem(), + %% Timer on dead process + ?line P1 = spawn(fun () -> ok end), + ?line wait_until(fun () -> process_is_cleaned_up(P1) end), + ?line T1 = erlang:start_timer(10000, P1, "hej"), + ?line T2 = erlang:send_after(10000, P1, "hej"), + ?line Mem = mem(), + ?line false = erlang:read_timer(T1), + ?line false = erlang:read_timer(T2), + ?line Mem = mem(), + %% Process dies before timeout + ?line P2 = spawn(fun () -> receive after 500 -> ok end end), + ?line T3 = erlang:start_timer(10000, P2, "hej"), + ?line T4 = erlang:send_after(10000, P2, "hej"), + ?line true = Mem < mem(), + ?line true = is_integer(erlang:read_timer(T3)), + ?line true = is_integer(erlang:read_timer(T4)), + ?line wait_until(fun () -> process_is_cleaned_up(P2) end), + ?line false = erlang:read_timer(T3), + ?line false = erlang:read_timer(T4), + ?line Mem = mem(), + %% Cancel timer + ?line P3 = spawn(fun () -> receive after 20000 -> ok end end), + ?line T5 = erlang:start_timer(10000, P3, "hej"), + ?line T6 = erlang:send_after(10000, P3, "hej"), + ?line true = Mem < mem(), + ?line true = is_integer(erlang:cancel_timer(T5)), + ?line true = is_integer(erlang:cancel_timer(T6)), + ?line false = erlang:read_timer(T5), + ?line false = erlang:read_timer(T6), + ?line exit(P3, kill), + ?line Mem = mem(), + %% Timeout + ?line Ref = make_ref(), + ?line T7 = erlang:start_timer(500, self(), Ref), + ?line T8 = erlang:send_after(500, self(), Ref), + ?line true = Mem < mem(), + ?line true = is_integer(erlang:read_timer(T7)), + ?line true = is_integer(erlang:read_timer(T8)), + ?line receive {timeout, T7, Ref} -> ok end, + ?line receive Ref -> ok end, + ?line Mem = mem(), + ?line ok. + + +evil_timers(doc) -> []; +evil_timers(suite) -> []; +evil_timers(Config) when is_list(Config) -> + %% Create a composite term consisting of at least: + %% * externals (remote pids, ports, and refs) + %% * large (off heap) binaries + %% * small (heap) binaries + %% * funs + %% * bignums + %% * tuples + %% * lists + %% since data of these types have to be adjusted if moved + %% in memory + ?line Self = self(), + ?line R1 = make_ref(), + ?line Node = start_slave(), + ?line spawn_link(Node, + fun () -> + Self ! {R1, + [lists:sublist(erlang:ports(), 3), + [make_ref(), make_ref(), make_ref()], + lists:sublist(processes(), 3), + [fun () -> gurka end, + fun (A) -> A + 1 end, + fun (A, B) -> A + B end]]} + end), + ?line ExtList = receive {R1, L} -> L end, + ?line stop_slave(Node), + ?line BinList = [<<"bla">>, + <<"blipp">>, + <<"blupp">>, + list_to_binary(lists:duplicate(1000000,$a)), + list_to_binary(lists:duplicate(1000000,$b)), + list_to_binary(lists:duplicate(1000000,$c))], + ?line FunList = [fun () -> gurka end, + fun (A) -> A + 1 end, + fun (A, B) -> A + B end], + ?line PidList = lists:sublist(processes(), 3), + ?line PortList = lists:sublist(erlang:ports(), 3), + ?line RefList = [make_ref(), make_ref(), make_ref()], + ?line BigList = [111111111111, 22222222222222, 333333333333333333], + ?line Msg = {BinList,[FunList,{RefList,ExtList,PidList,PortList,BigList}]}, + %% ?line ?t:format("Msg=~p~n",[Msg]), + + ?line Prio = process_flag(priority, max), + %% + %% In the smp case there are four major cases we want to test: + %% + %% 1. A timer started with erlang:start_timer(Time, Receiver, Msg), + %% where Msg is a composite term, expires, and the receivers main + %% lock *can not* be acquired immediately (typically when the + %% receiver *is* running). + %% + %% The wrap tuple ({timeout, TRef, Msg}) will in this case + %% be allocated in the previously allocated message buffer along + %% with Msg, i.e. the previously allocated message buffer will be + %% reallocated and potentially moved. + ?line TimeOutMsgs0 = evil_setup_timers(200, Self, Msg), + ?line RecvTimeOutMsgs0 = evil_recv_timeouts(200), + %% 2. A timer started with erlang:start_timer(Time, Receiver, Msg), + %% where Msg is an immediate term, expires, and the receivers main + %% lock *can not* be acquired immediately (typically when the + %% receiver *is* running). + %% + %% The wrap tuple will in this case be allocated in a new + %% message buffer. + ?line TimeOutMsgs1 = evil_setup_timers(200, Self, immediate), + ?line RecvTimeOutMsgs1 = evil_recv_timeouts(200), + %% 3. A timer started with erlang:start_timer(Time, Receiver, Msg), + %% where Msg is a composite term, expires, and the receivers main + %% lock *can* be acquired immediately (typically when the receiver + %% *is not* running). + %% + %% The wrap tuple will in this case be allocated on the receivers + %% heap, and Msg is passed in the previously allocated message + %% buffer. + ?line R2 = make_ref(), + ?line spawn_link(fun () -> + Self ! {R2, evil_setup_timers(200, Self, Msg)} + end), + ?line receive after 1000 -> ok end, + ?line TimeOutMsgs2 = receive {R2, TOM2} -> TOM2 end, + ?line RecvTimeOutMsgs2 = evil_recv_timeouts(200), + %% 4. A timer started with erlang:start_timer(Time, Receiver, Msg), + %% where Msg is an immediate term, expires, and the Receivers main + %% lock *can* be acquired immediately (typically when the receiver + %% *is not* running). + %% + %% The wrap tuple will in this case be allocated on the receivers + %% heap. + ?line R3 = make_ref(), + ?line spawn_link(fun () -> + Self ! {R3, evil_setup_timers(200,Self,immediate)} + end), + ?line receive after 1000 -> ok end, + ?line TimeOutMsgs3 = receive {R3, TOM3} -> TOM3 end, + ?line RecvTimeOutMsgs3 = evil_recv_timeouts(200), + + %% Garge collection will hopefully crash the emulator if something + %% is wrong... + ?line garbage_collect(), + ?line garbage_collect(), + ?line garbage_collect(), + + %% Make sure we got the timeouts we expected + %% + %% Note timeouts are *not* guaranteed to be delivered in order + ?line ok = match(lists:sort(RecvTimeOutMsgs0), lists:sort(TimeOutMsgs0)), + ?line ok = match(lists:sort(RecvTimeOutMsgs1), lists:sort(TimeOutMsgs1)), + ?line ok = match(lists:sort(RecvTimeOutMsgs2), lists:sort(TimeOutMsgs2)), + ?line ok = match(lists:sort(RecvTimeOutMsgs3), lists:sort(TimeOutMsgs3)), + + ?line process_flag(priority, Prio), + ?line ok. + +evil_setup_timers(N, Receiver, Msg) -> + ?line evil_setup_timers(0, N, Receiver, Msg, []). + +evil_setup_timers(N, N, _Receiver, _Msg, TOs) -> + ?line TOs; +evil_setup_timers(N, Max, Receiver, Msg, TOs) -> + ?line TRef = erlang:start_timer(N, Receiver, Msg), + ?line evil_setup_timers(N+1, Max, Receiver, Msg, [{timeout,TRef,Msg}|TOs]). + + +evil_recv_timeouts(M) -> + ?line evil_recv_timeouts([], 0, M). + +evil_recv_timeouts(TOs, N, N) -> + ?line TOs; +evil_recv_timeouts(TOs, N, M) -> + ?line receive + {timeout, _, _} = TO -> + ?line evil_recv_timeouts([TO|TOs], N+1, M) + after 0 -> + ?line evil_recv_timeouts(TOs, N, M) + end. + +registered_process(doc) -> []; +registered_process(suite) -> []; +registered_process(Config) when is_list(Config) -> + ?line Mem = mem(), + %% Cancel + ?line T1 = erlang:start_timer(500, ?MODULE, "hej"), + ?line T2 = erlang:send_after(500, ?MODULE, "hej"), + ?line undefined = whereis(?MODULE), + ?line true = Mem < mem(), + ?line true = is_integer(erlang:cancel_timer(T1)), + ?line true = is_integer(erlang:cancel_timer(T2)), + ?line false = erlang:read_timer(T1), + ?line false = erlang:read_timer(T2), + ?line Mem = mem(), + %% Timeout register after start + ?line Ref1 = make_ref(), + ?line T3 = erlang:start_timer(500, ?MODULE, Ref1), + ?line T4 = erlang:send_after(500, ?MODULE, Ref1), + ?line undefined = whereis(?MODULE), + ?line true = Mem < mem(), + ?line true = is_integer(erlang:read_timer(T3)), + ?line true = is_integer(erlang:read_timer(T4)), + ?line true = register(?MODULE, self()), + ?line receive {timeout, T3, Ref1} -> ok end, + ?line receive Ref1 -> ok end, + ?line Mem = mem(), + %% Timeout register before start + ?line Ref2 = make_ref(), + ?line T5 = erlang:start_timer(500, ?MODULE, Ref2), + ?line T6 = erlang:send_after(500, ?MODULE, Ref2), + ?line true = Mem < mem(), + ?line true = is_integer(erlang:read_timer(T5)), + ?line true = is_integer(erlang:read_timer(T6)), + ?line receive {timeout, T5, Ref2} -> ok end, + ?line receive Ref2 -> ok end, + ?line Mem = mem(), + ?line true = unregister(?MODULE), + ?line ok. + +mem() -> + AA = erlang:system_info(allocated_areas), + {value,{bif_timer,Mem}} = lists:keysearch(bif_timer, 1, AA), + Mem. + +process_is_cleaned_up(P) when is_pid(P) -> + undefined == erts_debug:get_internal_state({process_status, P}). + +wait_until(Pred) when is_function(Pred) -> + case catch Pred() of + true -> ok; + _ -> receive after 50 -> ok end, wait_until(Pred) + end. + +get(Time, Msg) -> + receive + Msg -> + ok + after Time + -> + no_message + end. + +get_msg() -> + receive + Msg -> + {ok, Msg} + after 0 -> + empty + end. + +start_slave() -> + ?line {A, B, C} = now(), + ?line Pa = filename:dirname(code:which(?MODULE)), + ?line Name = atom_to_list(?MODULE) ++ "-" ++ integer_to_list(A+B+C), + {ok, Node} = ?t:start_node(Name, slave, [{args, "-pa " ++ Pa}]), + Node. + +stop_slave(Node) -> + test_server:stop_node(Node). + +collect(Last) -> + collect(Last, []). + +receive_one() -> + receive + Msg -> + Msg + end. + +collect(Last, Msgs0) -> + Msg = receive_one(), + Msgs = Msgs0 ++ [Msg], + case Msg of + Last -> + Msgs; + _ -> + collect(Last, Msgs) + end. + +match(X, X) -> + %erlang:display({match, X}), + ok; +match(X, Y) -> + %erlang:display({mismatch, X, Y}), + match_aux(X, Y). + +match_aux(X, X) -> + unexpected_error; +match_aux(X, Y) when is_list(X), is_list(Y), length(X) =/= length(Y) -> + %% erlang:display({mismatch, X, Y}), + {list_length_mismatch, length(X), length(Y)}; +match_aux([X|Xs], [X|Ys]) -> + match_aux(Xs, Ys); +match_aux([X|_], [Y|_]) -> + match_aux(X, Y); +match_aux(X, Y) when is_tuple(X), is_tuple(Y), size(X) =/= size(Y) -> + %% erlang:display({mismatch, X, Y}), + {tuple_size_mismatch, size(X), size(Y)}; +match_aux(X, Y) when is_tuple(X), is_tuple(Y) -> + match_aux(tuple_to_list(X), tuple_to_list(Y)); +match_aux(X, Y) -> + %% erlang:display({mismatch, X, Y}), + {mismatch, type(X), type(Y)}. + +type(X) when is_list(X) -> list; +type(X) when is_tuple(X) -> tuple; +type(X) when is_float(X) -> float; +type(X) when is_integer(X) -> integer; +type(X) when is_pid(X) -> {pid, node(X)}; +type(X) when is_reference(X) -> {reference, node(X)}; +type(X) when is_port(X) -> {port, node(X)}; +type(X) when is_binary(X) -> binary; +type(X) when is_atom(X) -> atom; +type(_) -> unknown. + + diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl new file mode 100644 index 0000000000..2c60ba6838 --- /dev/null +++ b/erts/emulator/test/trace_SUITE.erl @@ -0,0 +1,1496 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(trace_SUITE). + +%%% +%%% Tests the trace BIF. +%%% + +-export([all/1, receive_trace/1, self_send/1, + timeout_trace/1, send_trace/1, + procs_trace/1, dist_procs_trace/1, + suspend/1, mutual_suspend/1, suspend_exit/1, suspender_exit/1, + suspend_system_limit/1, suspend_opts/1, suspend_waiting/1, + new_clear/1, existing_clear/1, + set_on_spawn/1, set_on_first_spawn/1, cpu_timestamp/1, + system_monitor_args/1, more_system_monitor_args/1, + system_monitor_long_gc_1/1, system_monitor_long_gc_2/1, + system_monitor_large_heap_1/1, system_monitor_large_heap_2/1, + bad_flag/1, trace_delivered/1]). + +-include("test_server.hrl"). + +%%% Internal exports +-export([process/1]). + +all(suite) -> + [cpu_timestamp, receive_trace, self_send, timeout_trace, send_trace, + procs_trace, dist_procs_trace, + suspend, mutual_suspend, suspend_exit, suspender_exit, + suspend_system_limit, suspend_opts, suspend_waiting, + new_clear, existing_clear, + set_on_spawn, set_on_first_spawn, + system_monitor_args, more_system_monitor_args, + system_monitor_long_gc_1, system_monitor_long_gc_2, + system_monitor_large_heap_1, system_monitor_large_heap_2, + bad_flag, trace_delivered]. + + +%% No longer testing anything, just reporting whether cpu_timestamp +%% is enabled or not. +cpu_timestamp(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(5)), + + %% Test whether cpu_timestamp is implemented on this platform. + ?line Works = try erlang:trace(all, true, [cpu_timestamp]) of + _ -> + ?line erlang:trace(all, false, [cpu_timestamp]), + true + catch + error:badarg -> false + end, + + ?line test_server:timetrap_cancel(Dog), + {comment,case Works of + false -> "cpu_timestamp is NOT implemented/does not work"; + true -> "cpu_timestamp works" + end}. + + +%% Tests that trace(Pid, How, ['receive']) works. + +receive_trace(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(5)), + ?line Receiver = fun_spawn(fun receiver/0), + ?line process_flag(trap_exit, true), + + %% Trace the process; make sure that we receive the trace messages. + ?line 1 = erlang:trace(Receiver, true, ['receive']), + ?line Hello = {hello, world}, + ?line Receiver ! Hello, + ?line {trace, Receiver, 'receive', Hello} = receive_first(), + ?line Hello2 = {hello, again, world}, + ?line Receiver ! Hello2, + ?line {trace, Receiver, 'receive', Hello2} = receive_first(), + ?line receive_nothing(), + + %% Another process should not be able to trace Receiver. + ?line Intruder = fun_spawn(fun() -> erlang:trace(Receiver, true, ['receive']) end), + ?line {'EXIT', Intruder, {badarg, _}} = receive_first(), + + %% Untrace the process; we should not receive anything. + ?line 1 = erlang:trace(Receiver, false, ['receive']), + ?line Receiver ! {hello, there}, + ?line Receiver ! any_garbage, + ?line receive_nothing(), + + %% Done. + ?line test_server:timetrap_cancel(Dog), + ok. + +self_send(doc) -> ["Test that traces are generated for messages sent ", + "and received to/from self()."]; +self_send(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(5)), + ?line Fun = + fun(Self, Parent) -> receive + go_ahead -> + self() ! from_myself, + Self(Self, Parent); + from_myself -> + Parent ! done + end + end, + ?line Self = self(), + ?line SelfSender = fun_spawn(Fun, [Fun, Self]), + ?line erlang:trace(SelfSender, true, ['receive', 'send']), + ?line SelfSender ! go_ahead, + ?line receive {trace, SelfSender, 'receive', go_ahead} -> ok end, + ?line receive {trace, SelfSender, 'receive', from_myself} -> ok end, + ?line receive + {trace,SelfSender,send,from_myself,SelfSender} -> ok + end, + ?line receive {trace,SelfSender,send,done,Self} -> ok end, + ?line receive done -> ok end, + + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Test that we can receive timeout traces. +timeout_trace(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(5)), + + ?line Process = fun_spawn(fun process/0), + ?line 1 = erlang:trace(Process, true, ['receive']), + ?line Process ! timeout_please, + ?line {trace, Process, 'receive', timeout_please} = receive_first(), + ?line {trace, Process, 'receive', timeout} = receive_first(), + ?line receive_nothing(), + + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Tests that trace(Pid, How, [send]) works. + +send_trace(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(5)), + ?line process_flag(trap_exit, true), + ?line Sender = fun_spawn(fun sender/0), + ?line Receiver = fun_spawn(fun receiver/0), + + %% Check that a message sent to another process is traced. + ?line 1 = erlang:trace(Sender, true, [send]), + ?line Sender ! {send_please, Receiver, to_receiver}, + ?line {trace, Sender, send, to_receiver, Receiver} = receive_first(), + ?line receive_nothing(), + + %% Check that a message sent to this process is traced. + ?line Sender ! {send_please, self(), to_myself}, + ?line receive to_myself -> ok end, + ?line Self = self(), + ?line {trace, Sender, send, to_myself, Self} = receive_first(), + ?line receive_nothing(), + + %% Another process should not be able to trace Sender. + ?line Intruder = fun_spawn(fun() -> erlang:trace(Sender, true, [send]) end), + ?line {'EXIT', Intruder, {badarg, _}} = receive_first(), + + %% Untrace the sender process and make sure that we receive no more + %% trace messages. + ?line 1 = erlang:trace(Sender, false, [send]), + ?line Sender ! {send_please, Receiver, to_receiver}, + ?line Sender ! {send_please, self(), to_myself_again}, + ?line receive to_myself_again -> ok end, + ?line receive_nothing(), + + %% Done. + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Test trace(Pid, How, [procs]). +procs_trace(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(5)), + ?line Name = list_to_atom(atom_to_list(?MODULE)++"_procs_trace"), + ?line Self = self(), + ?line process_flag(trap_exit, true), + %% + ?line Proc1 = spawn_link(?MODULE, process, [Self]), + ?line io:format("Proc1 = ~p ~n", [Proc1]), + ?line Proc2 = spawn(?MODULE, process, [Self]), + ?line io:format("Proc2 = ~p ~n", [Proc2]), + %% + ?line 1 = erlang:trace(Proc1, true, [procs]), + ?line MFA = {?MODULE, process, [Self]}, + %% + %% spawn, link + ?line Proc1 ! {spawn_link_please, Self, MFA}, + ?line Proc3 = receive {spawned, Proc1, P3} -> P3 end, + ?line {trace, Proc1, spawn, Proc3, MFA} = receive_first(), + ?line io:format("Proc3 = ~p ~n", [Proc3]), + ?line {trace, Proc1, link, Proc3} = receive_first(), + ?line receive_nothing(), + %% + %% getting_unlinked by exit() + ?line Proc1 ! {trap_exit_please, true}, + ?line Reason3 = make_ref(), + ?line Proc1 ! {send_please, Proc3, {exit_please, Reason3}}, + ?line receive {Proc1, {'EXIT', Proc3, Reason3}} -> ok end, + ?line {trace, Proc1, getting_unlinked, Proc3} = receive_first(), + ?line Proc1 ! {trap_exit_please, false}, + ?line receive_nothing(), + %% + %% link + ?line Proc1 ! {link_please, Proc2}, + ?line {trace, Proc1, link, Proc2} = receive_first(), + ?line receive_nothing(), + %% + %% unlink + ?line Proc1 ! {unlink_please, Proc2}, + ?line {trace, Proc1, unlink, Proc2} = receive_first(), + ?line receive_nothing(), + %% + %% getting_linked + ?line Proc2 ! {link_please, Proc1}, + ?line {trace, Proc1, getting_linked, Proc2} = receive_first(), + ?line receive_nothing(), + %% + %% getting_unlinked + ?line Proc2 ! {unlink_please, Proc1}, + ?line {trace, Proc1, getting_unlinked, Proc2} = receive_first(), + ?line receive_nothing(), + %% + %% register + ?line true = register(Name, Proc1), + ?line {trace, Proc1, register, Name} = receive_first(), + ?line receive_nothing(), + %% + %% unregister + ?line true = unregister(Name), + ?line {trace, Proc1, unregister, Name} = receive_first(), + ?line receive_nothing(), + %% + %% exit (with registered name, due to link) + ?line Reason4 = make_ref(), + ?line Proc1 ! {spawn_link_please, Self, MFA}, + ?line Proc4 = receive {spawned, Proc1, P4} -> P4 end, + ?line {trace, Proc1, spawn, Proc4, MFA} = receive_first(), + ?line io:format("Proc4 = ~p ~n", [Proc4]), + ?line {trace, Proc1, link, Proc4} = receive_first(), + ?line Proc1 ! {register_please, Name, Proc1}, + ?line {trace, Proc1, register, Name} = receive_first(), + ?line Proc4 ! {exit_please, Reason4}, + ?line receive {'EXIT', Proc1, Reason4} -> ok end, + ?line {trace, Proc1, exit, Reason4} = receive_first(), + ?line {trace, Proc1, unregister, Name} = receive_first(), + ?line receive_nothing(), + %% + %% exit (not linked to tracing process) + ?line 1 = erlang:trace(Proc2, true, [procs]), + ?line Reason2 = make_ref(), + ?line Proc2 ! {exit_please, Reason2}, + ?line {trace, Proc2, exit, Reason2} = receive_first(), + ?line receive_nothing(), + %% + %% Done. + ?line test_server:timetrap_cancel(Dog), + ok. + + +dist_procs_trace(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(15)), + ?line OtherName = atom_to_list(?MODULE)++"_dist_procs_trace", + ?line {ok, OtherNode} = start_node(OtherName), + ?line Self = self(), + ?line process_flag(trap_exit, true), + %% + ?line Proc1 = spawn_link(?MODULE, process, [Self]), + ?line io:format("Proc1 = ~p ~n", [Proc1]), + ?line Proc2 = spawn(OtherNode, ?MODULE, process, [Self]), + ?line io:format("Proc2 = ~p ~n", [Proc2]), + %% + ?line 1 = erlang:trace(Proc1, true, [procs]), + ?line MFA = {?MODULE, process, [Self]}, + %% + %% getting_unlinked by exit() + ?line Proc1 ! {spawn_link_please, Self, OtherNode, MFA}, + ?line Proc1 ! {trap_exit_please, true}, + ?line Proc3 = receive {spawned, Proc1, P3} -> P3 end, + ?line io:format("Proc3 = ~p ~n", [Proc3]), + ?line {trace, Proc1, getting_linked, Proc3} = receive_first(), + ?line Reason3 = make_ref(), + ?line Proc1 ! {send_please, Proc3, {exit_please, Reason3}}, + ?line receive {Proc1, {'EXIT', Proc3, Reason3}} -> ok end, + ?line {trace, Proc1, getting_unlinked, Proc3} = receive_first(), + ?line Proc1 ! {trap_exit_please, false}, + ?line receive_nothing(), + %% + %% link + ?line Proc1 ! {link_please, Proc2}, + ?line {trace, Proc1, link, Proc2} = receive_first(), + ?line receive_nothing(), + %% + %% unlink + ?line Proc1 ! {unlink_please, Proc2}, + ?line {trace, Proc1, unlink, Proc2} = receive_first(), + ?line receive_nothing(), + %% + %% getting_linked + ?line Proc2 ! {link_please, Proc1}, + ?line {trace, Proc1, getting_linked, Proc2} = receive_first(), + ?line receive_nothing(), + %% + %% getting_unlinked + ?line Proc2 ! {unlink_please, Proc1}, + ?line {trace, Proc1, getting_unlinked, Proc2} = receive_first(), + ?line receive_nothing(), + %% + %% exit (with registered name, due to link) + ?line Name = list_to_atom(OtherName), + ?line Reason2 = make_ref(), + ?line Proc1 ! {link_please, Proc2}, + ?line {trace, Proc1, link, Proc2} = receive_first(), + ?line Proc1 ! {register_please, Name, Proc1}, + ?line {trace, Proc1, register, Name} = receive_first(), + ?line Proc2 ! {exit_please, Reason2}, + ?line receive {'EXIT', Proc1, Reason2} -> ok end, + ?line {trace, Proc1, exit, Reason2} = receive_first(), + ?line {trace, Proc1, unregister, Name} = receive_first(), + ?line receive_nothing(), + %% + %% Done. + ?line true = stop_node(OtherNode), + ?line test_server:timetrap_cancel(Dog), + ok. + + + + +%% Tests trace(Pid, How, [set_on_spawn]). + +set_on_spawn(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(5)), + ?line Listener = fun_spawn(fun process/0), + + %% Create and trace a process with the set_on_spawn flag. + %% Make sure it is traced. + ?line Father_SOS = fun_spawn(fun process/0), + ?line 1 = erlang:trace(Father_SOS, true, [send, set_on_spawn]), + ?line true = is_send_traced(Father_SOS, Listener, sos_father), + + %% Have the process spawn of two children and test that they + %% are traced. + ?line [Child1, Child2] = spawn_children(Father_SOS, 2), + ?line true = is_send_traced(Child1, Listener, child1), + ?line true = is_send_traced(Child2, Listener, child2), + + %% Second generation. + [Child11, Child12] = spawn_children(Child1, 2), + ?line true = is_send_traced(Child11, Listener, child11), + ?line true = is_send_traced(Child12, Listener, child12), + + %% Done. + ?line test_server:timetrap_cancel(Dog), + ok. + +%% Tests trace(Pid, How, [set_on_first_spawn]). + +set_on_first_spawn(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(10)), + ?line Listener = fun_spawn(fun process/0), + + %% Create and trace a process with the set_on_first_spawn flag. + %% Make sure it is traced. + ?line Parent = fun_spawn(fun process/0), + ?line 1 = erlang:trace(Parent, true, [send, set_on_first_spawn]), + ?line is_send_traced(Parent, Listener, sos_father), + + %% Have the process spawn off three children and test that the + %% first is traced. + ?line [Child1, Child2, Child3] = spawn_children(Parent, 3), + ?line true = is_send_traced(Child1, Listener, child1), + ?line false = is_send_traced(Child2, Listener, child2), + ?line false = is_send_traced(Child3, Listener, child3), + ?line receive_nothing(), + + %% Done. + ?line test_server:timetrap_cancel(Dog), + ok. + + +system_monitor_args(doc) -> + ["Tests arguments to erlang:system_monitor/0-2)"]; +system_monitor_args(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(5)), + ?line Self = self(), + %% + ?line OldMonitor = erlang:system_monitor(undefined), + ?line undefined = erlang:system_monitor(Self, [{long_gc,0}]), + ?line MinT = case erlang:system_monitor() of + {Self,[{long_gc,T}]} when is_integer(T), T > 0 -> T; + Other1 -> test_server:fault(Other1) + end, + ?line {Self,[{long_gc,MinT}]} = erlang:system_monitor(), + ?line {Self,[{long_gc,MinT}]} = + erlang:system_monitor({Self,[{large_heap,0}]}), + ?line MinN = case erlang:system_monitor() of + {Self,[{large_heap,N}]} when is_integer(N), N > 0 -> N; + Other2 -> test_server:fault(Other2) + end, + ?line {Self,[{large_heap,MinN}]} = erlang:system_monitor(), + ?line {Self,[{large_heap,MinN}]} = + erlang:system_monitor(Self, [busy_port]), + ?line {Self,[busy_port]} = erlang:system_monitor(), + ?line {Self,[busy_port]} = + erlang:system_monitor({Self,[busy_dist_port]}), + ?line {Self,[busy_dist_port]} = erlang:system_monitor(), + ?line All = lists:sort([busy_port,busy_dist_port, + {long_gc,1},{large_heap,65535}]), + ?line {Self,[busy_dist_port]} = erlang:system_monitor(Self, All), + ?line {Self,A1} = erlang:system_monitor(), + ?line All = lists:sort(A1), + ?line {Self,A1} = erlang:system_monitor(Self, []), + ?line Pid = spawn(fun () -> receive {Self,die} -> exit(die) end end), + ?line Mref = erlang:monitor(process, Pid), + ?line undefined = erlang:system_monitor(Pid, All), + ?line {Pid,A2} = erlang:system_monitor(), + ?line All = lists:sort(A2), + ?line Pid ! {Self,die}, + ?line receive {'DOWN',Mref,_,_,_} -> ok end, + ?line undefined = erlang:system_monitor(OldMonitor), + ?line erlang:yield(), + ?line OldMonitor = erlang:system_monitor(), + %% + ?line {'EXIT',{badarg,_}} = (catch erlang:system_monitor(atom)), + ?line {'EXIT',{badarg,_}} = (catch erlang:system_monitor({})), + ?line {'EXIT',{badarg,_}} = (catch erlang:system_monitor({1})), + ?line {'EXIT',{badarg,_}} = (catch erlang:system_monitor({1,2,3})), + ?line {'EXIT',{badarg,_}} = + (catch erlang:system_monitor({Self,atom})), + ?line {'EXIT',{badarg,_}} = + (catch erlang:system_monitor(atom, atom)), + ?line {'EXIT',{badarg,_}} = + (catch erlang:system_monitor({Self,[busy_port|busy_dist_port]})), + ?line {'EXIT',{badarg,_}} = + (catch erlang:system_monitor(Self, [{long_gc,-1}])), + ?line {'EXIT',{badarg,_}} = + (catch erlang:system_monitor({Self,[{long_gc,atom}]})), + ?line {'EXIT',{badarg,_}} = + (catch erlang:system_monitor(Self,[{large_heap,-1}])), + ?line {'EXIT',{badarg,_}} = + (catch erlang:system_monitor({Self,[{large_heap,atom}]})), + %% Done. + ?line test_server:timetrap_cancel(Dog), + ok. + + +more_system_monitor_args(doc) -> + ["Tests arguments to erlang:system_monitor/0-2)"]; +more_system_monitor_args(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(5)), + + ?line try_l(64000), + ?line try_l(16#7ffffff), + ?line try_l(16#3fffffff), + ?line try_l(16#7fffffff), + ?line try_l(16#ffffffff), + + %% Done. + ?line test_server:timetrap_cancel(Dog), + ok. + +try_l(Val) -> + Self = self(), + Arbitrary1 = 77777, + Arbitrary2 = 88888, + + ?line erlang:system_monitor(undefined), + + ?line undefined = erlang:system_monitor(Self, [{long_gc,Val},{large_heap,Arbitrary1}]), + + ?line {Self,Comb0} = erlang:system_monitor(Self, [{long_gc,Arbitrary2},{large_heap,Val}]), + ?line [{large_heap,Arbitrary1},{long_gc,Val}] = lists:sort(Comb0), + + ?line {Self,Comb1} = erlang:system_monitor(undefined), + ?line [{large_heap,Val},{long_gc,Arbitrary2}] = lists:sort(Comb1). + +-define(LONG_GC_SLEEP, 670). + +system_monitor_long_gc_1(suite) -> + []; +system_monitor_long_gc_1(doc) -> + ["Tests erlang:system_monitor(Pid, [{long_gc,Time}])"]; +system_monitor_long_gc_1(Config) when is_list(Config) -> + erts_debug:set_internal_state(available_internal_state, true), + try + %% Add ?LONG_GC_SLEEP ms to all gc + ?line erts_debug:set_internal_state(test_long_gc_sleep, + ?LONG_GC_SLEEP), + ?line LoadFun = + fun () -> + garbage_collect(), + self() + end, + ?line long_gc(LoadFun, false) + after + erts_debug:set_internal_state(test_long_gc_sleep, 0), + erts_debug:set_internal_state(available_internal_state, false) + end. + +system_monitor_long_gc_2(suite) -> + []; +system_monitor_long_gc_2(doc) -> + ["Tests erlang:system_monitor(Pid, [{long_gc,Time}])"]; +system_monitor_long_gc_2(Config) when is_list(Config) -> + erts_debug:set_internal_state(available_internal_state, true), + try + %% Add ?LONG_GC_SLEEP ms to all gc + ?line erts_debug:set_internal_state(test_long_gc_sleep, + ?LONG_GC_SLEEP), + ?line Parent = self(), + ?line LoadFun = + fun () -> + Ref = make_ref(), + Pid = + spawn_link( + fun () -> + garbage_collect(), + Parent ! {Ref, self()} + end), + receive {Ref, Pid} -> Pid end + end, + ?line long_gc(LoadFun, true), + ?line long_gc(LoadFun, true), + ?line long_gc(LoadFun, true) + after + erts_debug:set_internal_state(test_long_gc_sleep, 0), + erts_debug:set_internal_state(available_internal_state, false) + end. + +long_gc(LoadFun, ExpectMonMsg) -> + ?line Self = self(), + ?line Time = 1, + ?line OldMonitor = erlang:system_monitor(Self, [{long_gc,Time}]), + ?line Pid = LoadFun(), + ?line Ref = erlang:trace_delivered(Pid), + ?line receive {trace_delivered, Pid, Ref} -> ok end, + ?line {Self,[{long_gc,Time}]} = erlang:system_monitor(OldMonitor), + ?line case {long_gc_check(Pid, Time, undefined), ExpectMonMsg} of + {ok, true} when Pid =/= Self -> + ok; + {ok, false} -> + ?line ?t:fail(unexpected_system_monitor_message_received); + {undefined, false} -> + ok; + {undefined, true} -> + ?line ?t:fail(no_system_monitor_message_received) + end. + +long_gc_check(Pid, Time, Result) -> + receive + {monitor,Pid,long_gc,L} = Monitor -> + case lists:foldl( + fun (_, error) -> + error; + ({timeout,T}, N) when is_integer(T), + Time =< T, T =< 10*?LONG_GC_SLEEP -> + %% OTP-7622. The time T must be within reasonable limits + %% for the test to pass. + N-1; + ({heap_size,_}, N) -> + N-1; + ({old_heap_size,_}, N) -> + N-1; + ({stack_size,_}, N) -> + N-1; + ({mbuf_size,_}, N) -> + N-1; + ({heap_block_size,_}, N) -> + N-1; + ({old_heap_block_size,_}, N) -> + N-1; + (_, _) -> + error + end, 7, L) of + 0 -> + long_gc_check(Pid, Time, ok); + error -> + {error,Monitor} + end; + {monitor,_,long_gc,_} -> + long_gc_check(Pid, Time, Result); + Other -> + {error,Other} + after 0 -> + Result + end. + +system_monitor_large_heap_1(suite) -> + []; +system_monitor_large_heap_1(doc) -> + ["Tests erlang:system_monitor(Pid, [{large_heap,Size}])"]; +system_monitor_large_heap_1(Config) when is_list(Config) -> + ?line LoadFun = + fun (Size) -> + List = seq(1,2*Size), + garbage_collect(), + true = lists:prefix([1], List), + self() + end, + ?line large_heap(LoadFun, false). + +system_monitor_large_heap_2(suite) -> + []; +system_monitor_large_heap_2(doc) -> + ["Tests erlang:system_monitor(Pid, [{large_heap,Size}])"]; +system_monitor_large_heap_2(Config) when is_list(Config) -> + ?line Parent = self(), + ?line LoadFun = + fun (Size) -> + Ref = make_ref(), + Pid = + spawn_opt(fun () -> + garbage_collect(), + Parent ! {Ref, self()} + end, + [link, {min_heap_size, 2*Size}]), + receive {Ref, Pid} -> Pid end + end, + ?line large_heap(LoadFun, true). + +large_heap(LoadFun, ExpectMonMsg) -> + ?line Dog = test_server:timetrap(test_server:seconds(20)), + %% + ?line Size = 65535, + ?line Self = self(), + ?line NewMonitor = {Self,[{large_heap,Size}]}, + ?line OldMonitor = erlang:system_monitor(NewMonitor), + ?line Pid = LoadFun(Size), + ?line Ref = erlang:trace_delivered(Pid), + ?line receive {trace_delivered, Pid, Ref} -> ok end, + ?line {Self,[{large_heap,Size}]} = erlang:system_monitor(OldMonitor), + ?line case {large_heap_check(Pid, Size, undefined), ExpectMonMsg} of + {ok, true} when Pid =/= Self -> + ?line ok; + {ok, false} -> + ?line ?t:fail(unexpected_system_monitor_message_received); + {undefined, false} -> + ?line ok; + {undefined, true} -> + ?line ?t:fail(no_system_monitor_message_received) + end, + %% + ?line test_server:timetrap_cancel(Dog), + ok. + +large_heap_check(Pid, Size, Result) -> + receive + {monitor,Pid,large_heap,L} = Monitor -> + case lists:foldl( + fun (_, error) -> + error; + ({heap_size,_}, N) -> + N-1; + ({old_heap_size,_}, N) -> + N-1; + ({stack_size,_}, N) -> + N-1; + ({mbuf_size,_}, N) -> + N-1; + ({heap_block_size,_}, N) -> + N-1; + ({old_heap_block_size,_}, N) -> + N-1; + (_, _) -> + error + end, 6, L) of + 0 -> + large_heap_check(Pid, Size, ok); + error -> + {error,Monitor} + end; + {monitor,_,large_heap,_} -> + large_heap_check(Pid, Size, Result); + Other -> + {error,Other} + after 0 -> + Result + end. + +seq(N, M) -> + seq(N, M, []). + +seq(M, M, R) -> + lists:reverse(R); +seq(N, M, R) -> + seq(N+1, M, [N|R]). + + +is_send_traced(Pid, Listener, Msg) -> + Pid ! {send_please, Listener, Msg}, + receive + Any -> + {trace, Pid, send, Msg, Listener} = Any, + true + after 1000 -> + false + end. + +%% This procedure assumes that the Parent process is send traced. + +spawn_children(Parent, Number) -> + spawn_children(Parent, Number, []). + +spawn_children(_Parent, 0, Result) -> + lists:reverse(Result); +spawn_children(Parent, Number, Result) -> + Self = self(), + Parent ! {spawn_please, Self, fun process/0}, + Child = + receive + {trace, Parent, send, {spawned, Pid}, Self} -> Pid + end, + receive + {spawned, Child} -> + spawn_children(Parent, Number-1, [Child|Result]) + end. + +suspend(doc) -> "Test erlang:suspend/1 and erlang:resume/1."; +suspend(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(2)), + + ?line Worker = fun_spawn(fun worker/0), + %% Suspend a process and test that it is suspended. + ?line ok = do_suspend(Worker, 10000), + + %% Done. + ?line test_server:timetrap_cancel(Dog), + ok. + +do_suspend(_Pid, 0) -> + ?line ok; +do_suspend(Pid, N) -> + %% Suspend a process and test that it is suspended. + ?line true = erlang:suspend_process(Pid), + ?line {status, suspended} = process_info(Pid, status), + + %% Unsuspend the process and make sure it starts working. + ?line true = erlang:resume_process(Pid), + ?line case process_info(Pid, status) of + {status, runnable} -> ?line ok; + {status, running} -> ?line ok; + {status, garbage_collecting} -> ?line ok; + ST -> ?line ?t:fail(ST) + end, + ?line erlang:yield(), + ?line do_suspend(Pid, N-1). + + + +mutual_suspend(doc) -> + []; +mutual_suspend(suite) -> + []; +mutual_suspend(Config) when is_list(Config) -> + ?line TimeoutSecs = 5*60, + ?line Dog = test_server:timetrap(test_server:minutes(TimeoutSecs)), + ?line Parent = self(), + ?line Fun = fun () -> + receive + {go, Pid} -> + do_mutual_suspend(Pid, 100000) + end, + Parent ! {done, self()}, + receive after infinity -> ok end + end, + ?line P1 = spawn_link(Fun), + ?line P2 = spawn_link(Fun), + ?line T1 = erlang:start_timer((TimeoutSecs - 5)*1000, self(), oops), + ?line T2 = erlang:start_timer((TimeoutSecs - 5)*1000, self(), oops), + ?line P1 ! {go, P2}, + ?line P2 ! {go, P1}, + ?line Res1 = receive + {done, P1} -> done; + {timeout,T1,_} -> timeout + end, + ?line Res2 = receive + {done, P2} -> done; + {timeout,T2,_} -> timeout + end, + ?line P1S = process_info(P1, status), + ?line P2S = process_info(P2, status), + ?line ?t:format("P1S=~p P2S=~p", [P1S, P2S]), + ?line false = {status, suspended} == P1S, + ?line false = {status, suspended} == P2S, + ?line unlink(P1), exit(P1, bang), + ?line unlink(P2), exit(P2, bang), + ?line done = Res1, + ?line done = Res2, + %% Done. + ?line test_server:timetrap_cancel(Dog), + ?line ok. + +do_mutual_suspend(_Pid, 0) -> + ?line ok; +do_mutual_suspend(Pid, N) -> + %% Suspend a process and test that it is suspended. + ?line true = erlang:suspend_process(Pid), + ?line {status, suspended} = process_info(Pid, status), + %% Unsuspend the process. + ?line true = erlang:resume_process(Pid), + ?line do_mutual_suspend(Pid, N-1). + +suspend_exit(doc) -> + []; +suspend_exit(suite) -> + []; +suspend_exit(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(2)), + ?line random:seed(4711,17,4711), + ?line do_suspend_exit(5000), + ?line test_server:timetrap_cancel(Dog), + ?line ok. + +do_suspend_exit(0) -> + ?line ok; +do_suspend_exit(N) -> + ?line Work = random:uniform(50), + ?line Parent = self(), + ?line {Suspendee, Mon2} + = spawn_monitor(fun () -> + suspend_exit_work(Work), + exit(normal) + end), + ?line {Suspender, Mon1} + = spawn_monitor( + fun () -> + suspend_exit_work(Work div 2), + Parent ! {doing_suspend, self()}, + case catch erlang:suspend_process(Suspendee) of + {'EXIT', _} -> + ok; + true -> + ?line erlang:resume_process(Suspendee) + end + end), + ?line receive + {doing_suspend, Suspender} -> + case N rem 2 of + 0 -> exit(Suspender, bang); + 1 -> ok + end + end, + ?line receive {'DOWN', Mon1, process, Suspender, _} -> ok end, + ?line receive {'DOWN', Mon2, process, Suspendee, _} -> ok end, + ?line do_suspend_exit(N-1). + + + + +suspend_exit_work(0) -> + ok; +suspend_exit_work(N) -> + process_info(self()), + suspend_exit_work(N-1). + +-define(CHK_SUSPENDED(P,B), chk_suspended(P, B, ?LINE)). + +chk_suspended(P, Bool, Line) -> + {Bool, Line} = {({status, suspended} == process_info(P, status)), Line}. + +suspender_exit(doc) -> + []; +suspender_exit(suite) -> + []; +suspender_exit(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(3)), + ?line P1 = spawn_link(fun () -> receive after infinity -> ok end end), + ?line {'EXIT', _} = (catch erlang:resume_process(P1)), + ?line {P2, M2} = spawn_monitor( + fun () -> + ?CHK_SUSPENDED(P1, false), + erlang:suspend_process(P1), + ?CHK_SUSPENDED(P1, true), + erlang:suspend_process(P1), + erlang:suspend_process(P1), + erlang:suspend_process(P1), + ?CHK_SUSPENDED(P1, true), + erlang:resume_process(P1), + erlang:resume_process(P1), + erlang:resume_process(P1), + ?CHK_SUSPENDED(P1, true), + erlang:resume_process(P1), + ?CHK_SUSPENDED(P1, false), + erlang:suspend_process(P1), + erlang:suspend_process(P1), + erlang:suspend_process(P1), + ?CHK_SUSPENDED(P1, true), + exit(bang) + end), + ?line receive + {'DOWN', M2,process,P2,R2} -> + ?line bang = R2, + ?line ?CHK_SUSPENDED(P1, false) + end, + ?line Parent = self(), + ?line {P3, M3} = spawn_monitor( + fun () -> + erlang:suspend_process(P1), + ?CHK_SUSPENDED(P1, true), + Parent ! self(), + receive after infinity -> ok end + end), + ?line {P4, M4} = spawn_monitor( + fun () -> + erlang:suspend_process(P1), + ?CHK_SUSPENDED(P1, true), + Parent ! self(), + receive after infinity -> ok end + end), + ?line {P5, M5} = spawn_monitor( + fun () -> + erlang:suspend_process(P1), + ?CHK_SUSPENDED(P1, true), + Parent ! self(), + receive after infinity -> ok end + end), + ?line {P6, M6} = spawn_monitor( + fun () -> + erlang:suspend_process(P1), + ?CHK_SUSPENDED(P1, true), + Parent ! self(), + receive after infinity -> ok end + end), + ?line {P7, M7} = spawn_monitor( + fun () -> + erlang:suspend_process(P1), + ?CHK_SUSPENDED(P1, true), + Parent ! self(), + receive after infinity -> ok end + end), + ?line receive P3 -> ok end, + ?line receive P4 -> ok end, + ?line receive P5 -> ok end, + ?line receive P6 -> ok end, + ?line receive P7 -> ok end, + ?line ?CHK_SUSPENDED(P1, true), + ?line exit(P3, bang), + ?line receive + {'DOWN',M3,process,P3,R3} -> + ?line bang = R3, + ?line ?CHK_SUSPENDED(P1, true) + end, + ?line exit(P4, bang), + ?line receive + {'DOWN',M4,process,P4,R4} -> + ?line bang = R4, + ?line ?CHK_SUSPENDED(P1, true) + end, + ?line exit(P5, bang), + ?line receive + {'DOWN',M5,process,P5,R5} -> + ?line bang = R5, + ?line ?CHK_SUSPENDED(P1, true) + end, + ?line exit(P6, bang), + ?line receive + {'DOWN',M6,process,P6,R6} -> + ?line bang = R6, + ?line ?CHK_SUSPENDED(P1, true) + end, + ?line exit(P7, bang), + ?line receive + {'DOWN',M7,process,P7,R7} -> + ?line bang = R7, + ?line ?CHK_SUSPENDED(P1, false) + end, + ?line unlink(P1), + ?line exit(P1, bong), + ?line test_server:timetrap_cancel(Dog), + ?line ok. + +suspend_system_limit(doc) -> + []; +suspend_system_limit(suite) -> + []; +suspend_system_limit(Config) when is_list(Config) -> + case os:getenv("ERL_EXTREME_TESTING") of + "true" -> + ?line Dog = test_server:timetrap(test_server:minutes(3*60)), + ?line P = spawn_link(fun () -> receive after infinity -> ok end end), + ?line suspend_until_system_limit(P), + ?line unlink(P), + ?line exit(P, bye), + ?line test_server:timetrap_cancel(Dog), + ?line ok; + _ -> + {skip, "Takes too long time for normal testing"} + end. + +suspend_until_system_limit(P) -> + ?line suspend_until_system_limit(P, 0, 0). + +suspend_until_system_limit(P, N, M) -> + NewM = case M of + 1 -> + ?line ?CHK_SUSPENDED(P, true), 2; + 1000000 -> + erlang:display(N), 1; + _ -> + M+1 + end, + ?line case catch erlang:suspend_process(P) of + true -> + suspend_until_system_limit(P, N+1, NewM); + {'EXIT', R} when R == system_limit; + element(1, R) == system_limit -> + ?line ?t:format("system limit at ~p~n", [N]), + ?line resume_from_system_limit(P, N, 0); + Error -> + ?line ?t:fail(Error) + end. + +resume_from_system_limit(P, 0, _) -> + ?line ?CHK_SUSPENDED(P, false), + ?line {'EXIT', _} = (catch erlang:resume_process(P)), + ?line ok; +resume_from_system_limit(P, N, M) -> + ?line NewM = case M of + 1 -> + ?line ?CHK_SUSPENDED(P, true), 2; + 1000000 -> + erlang:display(N), 1; + _ -> + M+1 + end, + ?line erlang:resume_process(P), + ?line resume_from_system_limit(P, N-1, NewM). + +-record(susp_info, {async = 0, + dbl_async = 0, + synced = 0, + async_once = 0}). + +suspend_opts(doc) -> + []; +suspend_opts(suite) -> + []; +suspend_opts(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:minutes(3)), + ?line Self = self(), + ?line wait_for_empty_runq(10), + ?line Tok = spawn_link(fun () -> + Self ! self(), + tok_trace_loop(Self, 0, 1000000000) + end), + ?line TC = 1000, + ?line receive Tok -> ok end, + ?line SF = fun (N, #susp_info {async = A, + dbl_async = AA, + synced = S, + async_once = AO} = Acc) -> + ?line erlang:suspend_process(Tok, [asynchronous]), + ?line Res = case {suspend_count(Tok), N rem 4} of + {0, 2} -> + ?line erlang:suspend_process(Tok, + [asynchronous]), + case suspend_count(Tok) of + 2 -> + ?line erlang:resume_process(Tok), + ?line Acc#susp_info{async = A+1}; + 0 -> + ?line erlang:resume_process(Tok), + ?line Acc#susp_info{async = A+1, + dbl_async = AA+1} + end; + {0, 1} -> + ?line erlang:suspend_process(Tok, + [asynchronous, + unless_suspending]), + case suspend_count(Tok) of + 1 -> + ?line Acc#susp_info{async = A+1}; + 0 -> + ?line Acc#susp_info{async = A+1, + async_once = AO+1} + end; + {0, 0} -> + ?line erlang:suspend_process(Tok, + [unless_suspending]), + ?line 1 = suspend_count(Tok), + ?line Acc#susp_info{async = A+1, + synced = S+1}; + {0, _} -> + ?line Acc#susp_info{async = A+1}; + _ -> + Acc + end, + ?line erlang:resume_process(Tok), + ?line erlang:yield(), + ?line Res + end, + ?line SI = repeat_acc(SF, TC, #susp_info{}), + ?line erlang:suspend_process(Tok, [asynchronous]), + %% Verify that it eventually suspends + ?line WaitTime0 = 10, + ?line WaitTime1 = case {erlang:system_info(debug_compiled), + erlang:system_info(lock_checking)} of + {false, false} -> + WaitTime0; + {false, true} -> + WaitTime0*5; + _ -> + WaitTime0*10 + end, + ?line WaitTime = case {erlang:system_info(schedulers_online), + erlang:system_info(logical_processors)} of + {Schdlrs, CPUs} when is_integer(CPUs), + Schdlrs =< CPUs -> + WaitTime1; + _ -> + WaitTime1*10 + end, + ?line receive after WaitTime -> ok end, + ?line 1 = suspend_count(Tok), + ?line erlang:suspend_process(Tok, [asynchronous]), + ?line 2 = suspend_count(Tok), + ?line erlang:suspend_process(Tok, [asynchronous]), + ?line 3 = suspend_count(Tok), + ?line erlang:suspend_process(Tok), + ?line 4 = suspend_count(Tok), + ?line erlang:suspend_process(Tok), + ?line 5 = suspend_count(Tok), + ?line erlang:suspend_process(Tok, [unless_suspending]), + ?line 5 = suspend_count(Tok), + ?line erlang:suspend_process(Tok, [unless_suspending, + asynchronous]), + ?line 5 = suspend_count(Tok), + ?line erlang:resume_process(Tok), + ?line erlang:resume_process(Tok), + ?line erlang:resume_process(Tok), + ?line erlang:resume_process(Tok), + ?line 1 = suspend_count(Tok), + ?line ?t:format("Main suspends: ~p~n" + "Main async: ~p~n" + "Double async: ~p~n" + "Async once: ~p~n" + "Synced: ~p~n", + [TC, + SI#susp_info.async, + SI#susp_info.dbl_async, + SI#susp_info.async_once, + SI#susp_info.synced]), + ?line case erlang:system_info(schedulers_online) of + 1 -> + ?line ok; + _ -> + ?line true = SI#susp_info.async =/= 0 + end, + ?line unlink(Tok), + ?line exit(Tok, bang), + ?line test_server:timetrap_cancel(Dog), + ?line ok. + +suspend_count(Suspendee) -> + suspend_count(self(), Suspendee). + +suspend_count(Suspender, Suspendee) -> + {suspending, SList} = process_info(Suspender, suspending), + + case lists:keysearch(Suspendee, 1, SList) of + {value, {_Suspendee, 0, 0}} -> + ?line ?t:fail({bad_suspendee_list, SList}); + {value, {Suspendee, Count, 0}} when is_integer(Count), Count > 0 -> + {status, suspended} = process_info(Suspendee, status), + Count; + {value, {Suspendee, 0, Outstanding}} when is_integer(Outstanding), + Outstanding > 0 -> + 0; + false -> + 0; + Error -> + ?line ?t:fail({bad_suspendee_list, Error, SList}) + end. + +repeat_acc(Fun, N, Acc) -> + repeat_acc(Fun, 0, N, Acc). + +repeat_acc(_Fun, N, N, Acc) -> + Acc; +repeat_acc(Fun, N, M, Acc) -> + repeat_acc(Fun, N+1, M, Fun(N, Acc)). + +%% Tests that waiting process can be suspended +%% (bug in R2D and earlier; see OTP-1488). + +suspend_waiting(doc) -> "Test that a waiting process can be suspended."; +suspend_waiting(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(5)), + + ?line Process = fun_spawn(fun process/0), + ?line receive after 1 -> ok end, + ?line true = erlang:suspend_process(Process), + ?line {status, suspended} = process_info(Process, status), + + %% Done. + ?line test_server:timetrap_cancel(Dog), + ok. + + + +new_clear(doc) -> + "Test that erlang:trace(new, true, ...) is cleared when tracer dies."; +new_clear(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(5)), + + ?line Tracer = spawn(fun receiver/0), + ?line 0 = erlang:trace(new, true, [send, {tracer, Tracer}]), + ?line {flags, [send]} = erlang:trace_info(new, flags), + ?line {tracer, Tracer} = erlang:trace_info(new, tracer), + ?line Mref = erlang:monitor(process, Tracer), + ?line true = exit(Tracer, done), + receive + {'DOWN',Mref,_,_,_} -> ok + end, + ?line {flags, []} = erlang:trace_info(new, flags), + ?line {tracer, []} = erlang:trace_info(new, tracer), + + %% Done. + ?line test_server:timetrap_cancel(Dog), + + ok. + + + +existing_clear(doc) -> + "Test that erlang:trace(all, false, ...) works without tracer."; +existing_clear(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(5)), + ?line Self = self(), + + ?line Tracer = fun_spawn(fun receiver/0), + ?line N = erlang:trace(existing, true, [send, {tracer, Tracer}]), + ?line {flags, [send]} = erlang:trace_info(Self, flags), + ?line {tracer, Tracer} = erlang:trace_info(Self, tracer), + ?line M = erlang:trace(all, false, [all]), + ?line io:format("Started trace on ~p processes and stopped on ~p~n", + [N, M]), + ?line {flags, []} = erlang:trace_info(Self, flags), + ?line {tracer, []} = erlang:trace_info(Self, tracer), + ?line M = N + 1, % Since trace could not be enabled on the tracer. + + %% Done. + ?line test_server:timetrap_cancel(Dog), + ok. + +bad_flag(doc) -> "Test that an invalid flag cause badarg"; +bad_flag(suite) -> []; +bad_flag(Config) when is_list(Config) -> + %% A bad flag could deadlock the SMP emulator in erts-5.5 + ?line {'EXIT', {badarg, _}} = (catch erlang:trace(new, + true, + [not_a_valid_flag])), + ?line ok. + +trace_delivered(doc) -> "Test erlang:trace_delivered/1"; +trace_delivered(suite) -> []; +trace_delivered(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(60)), + ?line TokLoops = 10000, + ?line Go = make_ref(), + ?line Parent = self(), + ?line Tok = spawn(fun () -> + receive Go -> gone end, + tok_trace_loop(Parent, 0, TokLoops) + end), + ?line 1 = erlang:trace(Tok, true, [procs]), + ?line Mon = erlang:monitor(process, Tok), + ?line NoOfTraceMessages = 4*TokLoops + 1, + ?line io:format("Expect a total of ~p trace messages~n", + [NoOfTraceMessages]), + ?line Tok ! Go, + ?line NoOfTraceMessages = drop_trace_until_down(Tok, Mon), + ?line receive + Msg -> + ?line ?t:fail({unexpected_message, Msg}) + after 1000 -> + ?line test_server:timetrap_cancel(Dog), + ?line ok + end. + +drop_trace_until_down(Proc, Mon) -> + drop_trace_until_down(Proc, Mon, false, 0, 0). + +drop_trace_until_down(Proc, Mon, TDRef, N, D) -> + case receive Msg -> Msg end of + {trace_delivered, Proc, TDRef} -> + io:format("~p trace messages on 'DOWN'~n", [D]), + io:format("Got a total of ~p trace messages~n", [N]), + N; + {'DOWN', Mon, process, Proc, _} -> + Ref = erlang:trace_delivered(Proc), + drop_trace_until_down(Proc, Mon, Ref, N, N); + Trace when is_tuple(Trace), + element(1, Trace) == trace, + element(2, Trace) == Proc -> + drop_trace_until_down(Proc, Mon, TDRef, N+1, D) + end. + +tok_trace_loop(_, N, N) -> + ok; +tok_trace_loop(Parent, N, M) -> + Name = 'A really stupid name which I will unregister at once', + link(Parent), + register(Name, self()), + unregister(Name), + unlink(Parent), + tok_trace_loop(Parent, N+1, M). + +%% Waits for and returns the first message in the message queue. + +receive_first() -> + receive + Any -> Any + end. + +%% Ensures that there is no message in the message queue. + +receive_nothing() -> + receive + Any -> + test_server:fail({unexpected_message, Any}) + after 200 -> + ok + end. + + +%%% Models for various kinds of processes. + +process(Dest) -> + receive + {send_please, To, What} -> + To ! What, + process(Dest); + {spawn_link_please, ReplyTo, {M, F, A}} -> + Pid = spawn_link(M, F, A), + ReplyTo ! {spawned, self(), Pid}, + process(Dest); + {spawn_link_please, ReplyTo, Node, {M, F, A}} -> + Pid = spawn_link(Node, M, F, A), + ReplyTo ! {spawned, self(), Pid}, + process(Dest); + {link_please, Pid} -> + link(Pid), + process(Dest); + {unlink_please, Pid} -> + unlink(Pid), + process(Dest); + {register_please, Name, Pid} -> + register(Name, Pid), + process(Dest); + {unregister_please, Name} -> + unregister(Name), + process(Dest); + {exit_please, Reason} -> + exit(Reason); + {trap_exit_please, State} -> + process_flag(trap_exit, State), + process(Dest); + Other -> + Dest ! {self(), Other}, + process(Dest) + after 3000 -> + exit(timeout) + end. + + +%% A smart process template. + +process() -> + receive + {spawn_please, ReplyTo, Fun} -> + Pid = fun_spawn(Fun), + ReplyTo ! {spawned, Pid}, + process(); + {send_please, To, What} -> + To ! What, + process(); + timeout_please -> + receive after 1 -> process() end; + _Other -> + process() + end. + + +%% Sends messages when ordered to. + +sender() -> + receive + {send_please, To, What} -> + To ! What, + sender() + end. + + +%% Just consumes messages from its message queue. + +receiver() -> + receive + _Any -> receiver() + end. + +%% Works as long as it receives CPU time. Will always be RUNNABLE. + +worker() -> + worker(0). + +worker(Number) -> + worker(Number+1). + +fun_spawn(Fun) -> + spawn_link(erlang, apply, [Fun, []]). + +fun_spawn(Fun, Args) -> + spawn_link(erlang, apply, [Fun, Args]). + + +start_node(Name) -> + Pa = filename:dirname(code:which(?MODULE)), + Cookie = atom_to_list(erlang:get_cookie()), + test_server:start_node(Name, slave, + [{args, "-setcookie " ++ Cookie ++" -pa " ++ Pa}]). + +stop_node(Node) -> + test_server:stop_node(Node). + + +wait_for_empty_runq(DeadLine) -> + case statistics(run_queue) of + 0 -> true; + RQLen -> + erlang:display("Waiting for empty run queue"), + MSDL = DeadLine*1000, + wait_for_empty_runq(MSDL, MSDL, RQLen) + end. + +wait_for_empty_runq(DeadLine, Left, RQLen) when Left =< 0 -> + issue_non_empty_runq_warning(DeadLine, RQLen), + false; +wait_for_empty_runq(DeadLine, Left, _RQLen) -> + Wait = 10, + UntilDeadLine = Left - Wait, + receive after Wait -> ok end, + case statistics(run_queue) of + 0 -> + erlang:display("Waited for " + ++ integer_to_list(DeadLine + - UntilDeadLine) + ++ " ms for empty run queue."), + true; + NewRQLen -> + wait_for_empty_runq(DeadLine, + UntilDeadLine, + NewRQLen) + end. + +issue_non_empty_runq_warning(DeadLine, RQLen) -> + PIs = lists:foldl( + fun (P, Acc) -> + case process_info(P, + [status, + initial_call, + current_function, + registered_name, + reductions, + message_queue_len]) of + [{status, Runnable} | _] = PI when Runnable /= waiting, + Runnable /= suspended -> + [[{pid, P} | PI] | Acc]; + _ -> + Acc + end + end, + [], + processes()), + ?t:format("WARNING: Unexpected runnable processes in system (waited ~p sec).~n" + " Run queue length: ~p~n" + " Self: ~p~n" + " Processes info: ~p~n", + [DeadLine div 1000, RQLen, self(), PIs]), + receive after 1000 -> ok end. diff --git a/erts/emulator/test/trace_bif_SUITE.erl b/erts/emulator/test/trace_bif_SUITE.erl new file mode 100644 index 0000000000..3f91f8dc08 --- /dev/null +++ b/erts/emulator/test/trace_bif_SUITE.erl @@ -0,0 +1,268 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(trace_bif_SUITE). + +-include("test_server.hrl"). + +-export([all/1]). +-export([trace_bif/1, trace_bif_timestamp/1, trace_on_and_off/1, trace_bif_local/1, + trace_bif_timestamp_local/1, trace_bif_return/1, not_run/1, + trace_info_old_code/1]). + +-export([bif_process/0]). + +all(suite) -> + case test_server:is_native(?MODULE) of + true -> [not_run]; + false -> + [trace_bif, trace_bif_timestamp, trace_on_and_off, + trace_bif_local, trace_bif_timestamp_local, + trace_bif_return, trace_info_old_code] + end. + +not_run(Config) when is_list(Config) -> + {skipped,"Native code"}. + +trace_on_and_off(doc) -> + "Tests switching tracing on and off."; +trace_on_and_off(Config) when is_list(Config) -> + ?line Pid = spawn(?MODULE, bif_process, []), + ?line Self = self(), + ?line 1 = erlang:trace(Pid, true, [call,timestamp]), + ?line {flags,[timestamp,call]} = erlang:trace_info(Pid,flags), + ?line {tracer, Self} = erlang:trace_info(Pid,tracer), + ?line 1 = erlang:trace(Pid, false, [timestamp]), + ?line {flags,[call]} = erlang:trace_info(Pid,flags), + ?line {tracer, Self} = erlang:trace_info(Pid,tracer), + ?line 1 = erlang:trace(Pid, false, [call]), + ?line {flags,[]} = erlang:trace_info(Pid,flags), + ?line {tracer, []} = erlang:trace_info(Pid,tracer), + ?line exit(Pid,kill), + ok. + +trace_bif(doc) -> "Test tracing BIFs."; +trace_bif(Config) when is_list(Config) -> + do_trace_bif([]). + +trace_bif_local(doc) -> "Test tracing BIFs with local flag."; +trace_bif_local(Config) when is_list(Config) -> + do_trace_bif([local]). + +do_trace_bif(Flags) -> + ?line Pid = spawn(?MODULE, bif_process, []), + ?line 1 = erlang:trace(Pid, true, [call]), + ?line erlang:trace_pattern({erlang,'_','_'}, [], Flags), + ?line Pid ! {do_bif, time, []}, + ?line receive_trace_msg({trace,Pid,call,{erlang,time, []}}), + ?line Pid ! {do_bif, statistics, [runtime]}, + ?line receive_trace_msg({trace,Pid,call, + {erlang,statistics, [runtime]}}), + + ?line Pid ! {do_time_bif}, + ?line receive_trace_msg({trace,Pid,call, + {erlang,time, []}}), + + ?line Pid ! {do_statistics_bif}, + ?line receive_trace_msg({trace,Pid,call, + {erlang,statistics, [runtime]}}), + + ?line 1 = erlang:trace(Pid, false, [call]), + ?line erlang:trace_pattern({erlang,'_','_'}, false, Flags), + ?line exit(Pid, die), + ok. + +trace_bif_timestamp(doc) -> "Test tracing BIFs with timestamps."; +trace_bif_timestamp(Config) when is_list(Config) -> + do_trace_bif_timestamp([]). + +trace_bif_timestamp_local(doc) -> + "Test tracing BIFs with timestamps and local flag."; +trace_bif_timestamp_local(Config) when is_list(Config) -> + do_trace_bif_timestamp([local]). + +do_trace_bif_timestamp(Flags) -> + ?line Pid=spawn(?MODULE, bif_process, []), + ?line 1 = erlang:trace(Pid, true, [call,timestamp]), + ?line erlang:trace_pattern({erlang,'_','_'}, [], Flags), + + ?line Pid ! {do_bif, time, []}, + ?line receive_trace_msg_ts({trace_ts,Pid,call,{erlang,time,[]}}), + + ?line Pid ! {do_bif, statistics, [runtime]}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {erlang,statistics, [runtime]}}), + + ?line Pid ! {do_time_bif}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {erlang,time, []}}), + + ?line Pid ! {do_statistics_bif}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {erlang,statistics, [runtime]}}), + + %% We should be able to turn off the timestamp. + ?line 1 = erlang:trace(Pid, false, [timestamp]), + + ?line Pid ! {do_statistics_bif}, + ?line receive_trace_msg({trace,Pid,call, + {erlang,statistics, [runtime]}}), + + ?line Pid ! {do_bif, statistics, [runtime]}, + ?line receive_trace_msg({trace,Pid,call, + {erlang,statistics, [runtime]}}), + + ?line 1 = erlang:trace(Pid, false, [call]), + ?line erlang:trace_pattern({erlang,'_','_'}, false, Flags), + + ?line exit(Pid, die), + ok. + +trace_bif_return(doc) -> + "Test tracing BIF's with return/return_to trace."; +trace_bif_return(Config) when is_list(Config) -> + ?line Pid=spawn(?MODULE, bif_process, []), + ?line 1 = erlang:trace(Pid, true, [call,timestamp,return_to]), + ?line erlang:trace_pattern({erlang,'_','_'}, [{'_',[],[{return_trace}]}], + [local]), + + + ?line Pid ! {do_bif, time, []}, + ?line receive_trace_msg_ts({trace_ts,Pid,call,{erlang,time,[]}}), + ?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from, + {erlang,time,0}}), + ?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to, + {?MODULE, bif_process,0}}), + + + ?line Pid ! {do_bif, statistics, [runtime]}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {erlang,statistics, [runtime]}}), + ?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from, + {erlang,statistics,1}}), + ?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to, + {?MODULE, bif_process,0}}), + + + ?line Pid ! {do_time_bif}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {erlang,time, []}}), + ?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from, + {erlang,time,0}}), + ?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to, + {?MODULE, bif_process,0}}), + + + + ?line Pid ! {do_statistics_bif}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {erlang,statistics, [runtime]}}), + ?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from, + {erlang,statistics,1}}), + ?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to, + {?MODULE, bif_process,0}}), + ok. + + +receive_trace_msg(Mess) -> + receive + Mess -> + ok; + Other -> + io:format("Expected: ~p,~nGot: ~p~n", [Mess, Other]), + ?t:fail() + after 5000 -> + io:format("Expected: ~p,~nGot: timeout~n", [Mess]), + ?t:fail() + end. + +receive_trace_msg_ts({trace_ts, Pid, call, {erlang,F,A}}) -> + receive + {trace_ts, Pid, call, {erlang, F, A}, _Ts} -> + ok; + Other -> + io:format("Expected: {trace, ~p, call, {~p, ~p, ~p}, TimeStamp}},~n" + "Got: ~p~n", + [Pid, erlang, F, A, Other]), + ?t:fail() + after 5000 -> + io:format("Got timeout~n", []), + ?t:fail() + end. + +receive_trace_msg_ts_return_from({trace_ts, Pid, return_from, {erlang,F,A}}) -> + receive + {trace_ts, Pid, return_from, {erlang, F, A}, _Value, _Ts} -> + ok; + Other -> + io:format("Expected: {trace_ts, ~p, return_from, {~p, ~p, ~p}, Value, TimeStamp}},~n" + "Got: ~p~n", + [Pid, erlang, F, A, Other]), + ?t:fail() + after 5000 -> + io:format("Got timeout~n", []), + ?t:fail() + end. + +receive_trace_msg_ts_return_to({trace_ts, Pid, return_to, {M,F,A}}) -> + receive + {trace_ts, Pid, return_to, {M, F, A}, _Ts} -> + ok; + Other -> + io:format("Expected: {trace_ts, ~p, return_to, {~p, ~p, ~p}, TimeStamp}},~n" + "Got: ~p~n", + [Pid, M, F, A, Other]), + ?t:fail() + after 5000 -> + io:format("Got timeout~n", []), + ?t:fail() + end. + +bif_process() -> + receive + {do_bif, Name, Args} -> + apply(erlang, Name, Args), + bif_process(); + {do_time_bif} -> + _ = time(), %Assignment tells compiler to keep call. + bif_process(); + {do_statistics_bif} -> + statistics(runtime), + bif_process(); + _Stuff -> + bif_process() + end. + + + +trace_info_old_code(doc) -> "trace_info on deleted module (OTP-5057)."; +trace_info_old_code(Config) when is_list(Config) -> + ?line MFA = {M,F,0} = {test,foo,0}, + ?line Fname = atom_to_list(M)++".erl", + ?line AbsForms = + [{attribute,1,module,M}, % -module(M). + {attribute,2,export,[{F,0}]}, % -export([F/0]). + {function,3,F,0, % F() -> + [{clause,4,[],[],[{atom,4,F}]}]}], % F. + %% + ?line {ok,M,Mbin} = compile:forms(AbsForms), + ?line {module,M} = code:load_binary(M, Fname, Mbin), + ?line true = erlang:delete_module(M), + ?line {traced,undefined} = erlang:trace_info(MFA, traced), + ok. diff --git a/erts/emulator/test/trace_call_count_SUITE.erl b/erts/emulator/test/trace_call_count_SUITE.erl new file mode 100644 index 0000000000..07aa7c8d8d --- /dev/null +++ b/erts/emulator/test/trace_call_count_SUITE.erl @@ -0,0 +1,362 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% +%%% Define to run outside of test server +%%% +%%% -define(STANDALONE,1). +%%% +%%% +%%% Define for debug output +%%% +%%% -define(debug,1). + +-module(trace_call_count_SUITE). + +%% Exported end user tests +-export([basic_test/0, on_and_off_test/0, info_test/0, + pause_and_restart_test/0, combo_test/0]). + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Test server related stuff +%% + +-ifdef(STANDALONE). +-define(config(A,B),config(A,B)). +-export([config/2]). +-else. +-include("test_server.hrl"). +-endif. + +-ifdef(debug). +-ifdef(STANDALONE). +-define(line, erlang:display({?MODULE,?LINE}), ). +-endif. +-define(dbgformat(A,B),io:format(A,B)). +-else. +-ifdef(STANDALONE). +-define(line, noop, ). +-endif. +-define(dbgformat(A,B),noop). +-endif. + +-ifdef(STANDALONE). +config(priv_dir,_) -> + ".". +-else. +%% When run in test server. +-export([all/1, init_per_testcase/2, fin_per_testcase/2, not_run/1]). +-export([basic/1, on_and_off/1, info/1, + pause_and_restart/1, combo/1]). + +init_per_testcase(_Case, Config) -> + ?line Dog=test_server:timetrap(test_server:seconds(30)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + erlang:trace_pattern({'_','_','_'}, false, [local,meta,call_count]), + erlang:trace_pattern(on_load, false, [local,meta,call_count]), + erlang:trace(all, false, [all]), + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +all(doc) -> + ["Test call count tracing of local function calls."]; +all(suite) -> + case test_server:is_native(?MODULE) of + true -> [not_run]; + false -> [basic, on_and_off, info, + pause_and_restart, combo] + end. + +not_run(Config) when is_list(Config) -> + {skipped,"Native code"}. + +basic(suite) -> + []; +basic(doc) -> + ["Tests basic call count trace"]; +basic(Config) when is_list(Config) -> + basic_test(). + +on_and_off(suite) -> + []; +on_and_off(doc) -> + ["Tests turning trace parameters on and off"]; +on_and_off(Config) when is_list(Config) -> + on_and_off_test(). + +info(suite) -> + []; +info(doc) -> + ["Tests the trace_info BIF"]; +info(Config) when is_list(Config) -> + info_test(). + +pause_and_restart(suite) -> + []; +pause_and_restart(doc) -> + ["Tests pausing and restarting call counters"]; +pause_and_restart(Config) when is_list(Config) -> + pause_and_restart_test(). + +combo(suite) -> + []; +combo(doc) -> + ["Tests combining local call trace and meta trace with call count trace"]; +combo(Config) when is_list(Config) -> + combo_test(). + +-endif. %-ifdef(STANDALONE). ... -else. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Result examination macros + +-define(CT(P,MFA),{trace,P,call,MFA}). +-define(CTT(P, MFA),{trace_ts,P,call,MFA,{_,_,_}}). +-define(RF(P,MFA,V),{trace,P,return_from,MFA,V}). +-define(RFT(P,MFA,V),{trace_ts,P,return_from,MFA,V,{_,_,_}}). +-define(RT(P,MFA),{trace,P,return_to,MFA}). +-define(RTT(P,MFA),{trace_ts,P,return_to,MFA,{_,_,_}}). + +%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% The Tests +%%% + +basic_test() -> + ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_count]), + ?line M = 1000, + %% + ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, true, [call_count]), + ?line 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, true, [call_count]), + ?line L = seq(1, M, fun(X) -> X+1 end), + ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count), + ?line {call_count,0} = erlang:trace_info({?MODULE,seq_r,3}, call_count), + ?line Lr = seq_r(1, M, fun(X) -> X+1 end), + ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count), + ?line {call_count,1} = erlang:trace_info({?MODULE,seq_r,3}, call_count), + ?line {call_count,M} = erlang:trace_info({?MODULE,seq_r,4}, call_count), + ?line L = lists:reverse(Lr), + %% + ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_count]), + ok. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +on_and_off_test() -> + ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_count]), + ?line M = 100, + %% + ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, true, [call_count]), + ?line L = seq(1, M, fun(X) -> X+1 end), + ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count), + ?line N = erlang:trace_pattern({?MODULE,'_','_'}, true, [call_count]), + ?line L = seq(1, M, fun(X) -> X+1 end), + ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count), + ?line P = erlang:trace_pattern({'_','_','_'}, true, [call_count]), + ?line L = seq(1, M, fun(X) -> X+1 end), + ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count), + ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, false, [call_count]), + ?line {call_count,false} = erlang:trace_info({?MODULE,seq,3}, call_count), + ?line L = seq(1, M, fun(X) -> X+1 end), + ?line {call_count,false} = erlang:trace_info({?MODULE,seq,3}, call_count), + ?line {call_count,0} = erlang:trace_info({?MODULE,seq_r,4}, call_count), + ?line Lr = seq_r(1, M, fun(X) -> X+1 end), + ?line {call_count,M} = erlang:trace_info({?MODULE,seq_r,4}, call_count), + ?line N = erlang:trace_pattern({?MODULE,'_','_'}, false, [call_count]), + ?line {call_count,false} = erlang:trace_info({?MODULE,seq_r,4}, call_count), + ?line Lr = seq_r(1, M, fun(X) -> X+1 end), + ?line {call_count,false} = erlang:trace_info({?MODULE,seq_r,4}, call_count), + ?line L = lists:reverse(Lr), + %% + ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_count]), + ok. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +info_test() -> + ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_count]), + %% + ?line 1 = erlang:trace_pattern({?MODULE,seq,3}, true, [call_count]), + ?line {call_count,0} = erlang:trace_info({?MODULE,seq,3}, call_count), + ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, pause, [call_count]), + ?line {call_count,0} = erlang:trace_info({?MODULE,seq,3}, call_count), + ?line {all,[_|_]=L} = erlang:trace_info({?MODULE,seq,3}, all), + ?line {value,{call_count,0}} = lists:keysearch(call_count, 1, L), + ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, restart, [call_count]), + ?line {call_count,0} = erlang:trace_info({?MODULE,seq,3}, call_count), + ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, false, [call_count]), + ?line {call_count,false} = erlang:trace_info({?MODULE,seq,3}, call_count), + ?line {all,false} = erlang:trace_info({?MODULE,seq,3}, all), + %% + ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_count]), + ok. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +pause_and_restart_test() -> + ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_count]), + ?line M = 100, + %% + ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, true, [call_count]), + ?line {call_count,0} = erlang:trace_info({?MODULE,seq,3}, call_count), + ?line L = seq(1, M, fun(X) -> X+1 end), + ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count), + ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, pause, [call_count]), + ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count), + ?line L = seq(1, M, fun(X) -> X+1 end), + ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count), + ?line 1 = erlang:trace_pattern({?MODULE,seq,'_'}, restart, [call_count]), + ?line {call_count,0} = erlang:trace_info({?MODULE,seq,3}, call_count), + ?line L = seq(1, M, fun(X) -> X+1 end), + ?line {call_count,M} = erlang:trace_info({?MODULE,seq,3}, call_count), + %% + ?line P = erlang:trace_pattern({'_','_','_'}, false, [call_count]), + ok. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +combo_test() -> + ?line Self = self(), + + ?line MetaMatchSpec = [{'_',[],[{return_trace}]}], + ?line Flags = lists:sort([call, return_to]), + ?line LocalTracer = spawn_link(fun () -> relay_n(5, Self) end), + ?line MetaTracer = spawn_link(fun () -> relay_n(9, Self) end), + ?line 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, [], [local]), + ?line 2 = erlang:trace_pattern({?MODULE,seq_r,'_'}, + MetaMatchSpec, + [{meta,MetaTracer}, call_count]), + ?line 1 = erlang:trace(Self, true, [{tracer,LocalTracer} | Flags]), + %% + ?line {traced,local} = + erlang:trace_info({?MODULE,seq_r,3}, traced), + ?line {match_spec,[]} = + erlang:trace_info({?MODULE,seq_r,3}, match_spec), + ?line {meta,MetaTracer} = + erlang:trace_info({?MODULE,seq_r,3}, meta), + ?line {meta_match_spec,MetaMatchSpec} = + erlang:trace_info({?MODULE,seq_r,3}, meta_match_spec), + ?line {call_count,0} = + erlang:trace_info({?MODULE,seq_r,3}, call_count), + %% + ?line {all,[_|_]=TraceInfo} = + erlang:trace_info({?MODULE,seq_r,3}, all), + ?line {value,{traced,local}} = + lists:keysearch(traced, 1, TraceInfo), + ?line {value,{match_spec,[]}} = + lists:keysearch(match_spec, 1, TraceInfo), + ?line {value,{meta,MetaTracer}} = + lists:keysearch(meta, 1, TraceInfo), + ?line {value,{meta_match_spec,MetaMatchSpec}} = + lists:keysearch(meta_match_spec, 1, TraceInfo), + ?line {value,{call_count,0}} = + lists:keysearch(call_count, 1, TraceInfo), + %% + ?line [3,2,1] = seq_r(1, 3, fun(X) -> X+1 end), + %% + ?line List = collect(100), + ?line {MetaR, LocalR} = + lists:foldl( + fun ({P,X}, {M,L}) when P == MetaTracer -> + {[X|M],L}; + ({P,X}, {M,L}) when P == LocalTracer -> + {M,[X|L]} + end, + {[],[]}, + List), + ?line Meta = lists:reverse(MetaR), + ?line Local = lists:reverse(LocalR), + ?line [?CTT(Self,{?MODULE,seq_r,[1,3,_]}), + ?CTT(Self,{?MODULE,seq_r,[1,3,_,[]]}), + ?CTT(Self,{?MODULE,seq_r,[2,3,_,[1]]}), + ?CTT(Self,{?MODULE,seq_r,[3,3,_,[2,1]]}), + ?RFT(Self,{?MODULE,seq_r,4},[3,2,1]), + ?RFT(Self,{?MODULE,seq_r,4},[3,2,1]), + ?RFT(Self,{?MODULE,seq_r,4},[3,2,1]), + ?RFT(Self,{?MODULE,seq_r,3},[3,2,1])] = Meta, + ?line [?CT(Self,{?MODULE,seq_r,[1,3,_]}), + ?CT(Self,{?MODULE,seq_r,[1,3,_,[]]}), + ?CT(Self,{?MODULE,seq_r,[2,3,_,[1]]}), + ?CT(Self,{?MODULE,seq_r,[3,3,_,[2,1]]}), + ?RT(Self,{?MODULE,combo_test,0})] = Local, + ?line {call_count,1} = erlang:trace_info({?MODULE,seq_r,3}, call_count), + ?line {call_count,3} = erlang:trace_info({?MODULE,seq_r,4}, call_count), + %% + ?line erlang:trace_pattern({'_','_','_'}, false, [local,meta,call_count]), + ?line erlang:trace_pattern(on_load, false, [local,meta,call_count]), + ?line erlang:trace(all, false, [all]), + ok. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local helpers + +%% Stack recursive seq +seq(Stop, Stop, Succ) when is_function(Succ) -> + [Stop]; +seq(Start, Stop, Succ) when is_function(Succ) -> + [Start | seq(Succ(Start), Stop, Succ)]. + + + +%% Tail recursive seq, result list is reversed +seq_r(Start, Stop, Succ) when is_function(Succ) -> + seq_r(Start, Stop, Succ, []). + +seq_r(Stop, Stop, _, R) -> + [Stop | R]; +seq_r(Start, Stop, Succ, R) -> + seq_r(Succ(Start), Stop, Succ, [Start | R]). + + + +%% Message relay process +relay_n(0, _) -> + ok; +relay_n(N, Dest) -> + receive Msg -> + Dest ! {self(), Msg}, + relay_n(N-1, Dest) + end. + + + +%% Collect received messages +collect(Time) -> + Ref = erlang:start_timer(Time, self(), done), + L = lists:reverse(collect([], Ref)), + ?dbgformat("Got: ~p~n",[L]), + L. + +collect(A, 0) -> + receive + Mess -> + collect([Mess | A], 0) + after 0 -> + A + end; +collect(A, Ref) -> + receive + {timeout, Ref, done} -> + collect(A, 0); + Mess -> + collect([Mess | A], Ref) + end. diff --git a/erts/emulator/test/trace_local_SUITE.erl b/erts/emulator/test/trace_local_SUITE.erl new file mode 100644 index 0000000000..24005774ba --- /dev/null +++ b/erts/emulator/test/trace_local_SUITE.erl @@ -0,0 +1,1259 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(trace_local_SUITE). +-compile({nowarn_deprecated_function, {erlang,hash,2}}). + +-export([basic_test/0, bit_syntax_test/0, return_test/0, + on_and_off_test/0, stack_grow_test/0, + info_test/0, delete_test/1, exception_test/1, + not_run/1]). + +-export([exported/1, exported_wrap/1, loop/4, apply_slave_async/5, + match/2, clause/2, id/1, undef/1, lists_reverse/2]). + +%% +%% Define to run outside of test server +%% +%% (rotten feature) +%% +%%-define(STANDALONE,1). + +%% +%% Define for debug output +%% +%%-define(debug,1). + +-ifdef(STANDALONE). +-define(config(A,B),config(A,B)). +-export([config/2]). +-define(DEFAULT_RECEIVE_TIMEOUT, 1000). +-else. +-include("test_server.hrl"). +-define(DEFAULT_RECEIVE_TIMEOUT, infinity). +-endif. + +-ifdef(debug). +-ifdef(STANDALONE). +-define(line, erlang:display({?MODULE,?LINE}), ). +-endif. +-define(dbgformat(A,B),io:format(A,B)). +-else. +-ifdef(STANDALONE). +-define(line, noop, ). +-endif. +-define(dbgformat(A,B),noop). +-endif. + +-ifdef(STANDALONE). +config(priv_dir,_) -> + ".". +-else. + +%%% When run in test server %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-export([all/1, basic/1, bit_syntax/1, + return/1, on_and_off/1, stack_grow/1,info/1, delete/1, + exception/1, exception_apply/1, + exception_function/1, exception_apply_function/1, + exception_nocatch/1, exception_nocatch_apply/1, + exception_nocatch_function/1, exception_nocatch_apply_function/1, + exception_meta/1, exception_meta_apply/1, + exception_meta_function/1, exception_meta_apply_function/1, + exception_meta_nocatch/1, exception_meta_nocatch_apply/1, + exception_meta_nocatch_function/1, + exception_meta_nocatch_apply_function/1, + init_per_testcase/2, fin_per_testcase/2]). +init_per_testcase(_Case, Config) -> + ?line Dog=test_server:timetrap(test_server:minutes(2)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + shutdown(), + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. +all(doc) -> + ["Test tracing of local function calls and return traces."]; +all(suite) -> + case test_server:is_native(?MODULE) of + true -> [not_run]; + false -> [basic, bit_syntax, return, on_and_off, stack_grow, info, delete, + exception, exception_apply, + exception_function, exception_apply_function, + exception_nocatch, exception_nocatch_apply, + exception_nocatch_function, + exception_nocatch_apply_function, + exception_meta, exception_meta_apply, + exception_meta_function, exception_meta_apply_function, + exception_meta_nocatch, exception_meta_nocatch_apply, + exception_meta_nocatch_function, + exception_meta_nocatch_apply_function] + end. + +not_run(Config) when is_list(Config) -> + {skipped,"Native code"}. + +basic(doc) -> + ["Tests basic local call-trace"]; +basic(Config) when is_list(Config) -> + basic_test(). + +bit_syntax(doc) -> + "OTP-7399: Make sure that code that uses the optimized bit syntax matching " + "can be traced without crashing the emulator."; +bit_syntax(Config) when is_list(Config) -> + bit_syntax_test(). + +return(doc) -> + ["Tests the different types of return trace"]; +return(Config) when is_list(Config) -> + return_test(). + +on_and_off(doc) -> + ["Tests turning trace parameters on and off, " + "both for trace and trace_pattern"]; +on_and_off(Config) when is_list(Config) -> + on_and_off_test(). + +stack_grow(doc) -> + ["Tests the stack growth during return traces"]; +stack_grow(Config) when is_list(Config) -> + stack_grow_test(). + +info(doc) -> + ["Tests the trace_info BIF"]; +info(Config) when is_list(Config) -> + info_test(). + +delete(doc) -> + ["Tests putting trace on deleted modules"]; +delete(Config) when is_list(Config) -> + delete_test(Config). + +exception(doc) -> + ["Tests exception_trace"]; +exception(Config) when is_list(Config) -> + exception_test([]). + +exception_apply(doc) -> + ["Tests exception_trace"]; +exception_apply(Config) when is_list(Config) -> + exception_test([apply]). + +exception_function(doc) -> + ["Tests exception_trace"]; +exception_function(Config) when is_list(Config) -> + exception_test([function]). + +exception_apply_function(doc) -> + ["Tests exception_trace"]; +exception_apply_function(Config) when is_list(Config) -> + exception_test([apply,function]). + +exception_nocatch(doc) -> + ["Tests exception_trace"]; +exception_nocatch(Config) when is_list(Config) -> + exception_test([nocatch]). + +exception_nocatch_apply(doc) -> + ["Tests exception_trace"]; +exception_nocatch_apply(Config) when is_list(Config) -> + exception_test([nocatch,apply]). + +exception_nocatch_function(doc) -> + ["Tests exception_trace"]; +exception_nocatch_function(Config) when is_list(Config) -> + exception_test([nocatch,function]). + +exception_nocatch_apply_function(doc) -> + ["Tests exception_trace"]; +exception_nocatch_apply_function(Config) when is_list(Config) -> + exception_test([nocatch,apply,function]). + +exception_meta(doc) -> + ["Tests meta exception_trace"]; +exception_meta(Config) when is_list(Config) -> + exception_test([meta]). + +exception_meta_apply(doc) -> + ["Tests meta exception_trace"]; +exception_meta_apply(Config) when is_list(Config) -> + exception_test([meta,apply]). + +exception_meta_function(doc) -> + ["Tests meta exception_trace"]; +exception_meta_function(Config) when is_list(Config) -> + exception_test([meta,function]). + +exception_meta_apply_function(doc) -> + ["Tests meta exception_trace"]; +exception_meta_apply_function(Config) when is_list(Config) -> + exception_test([meta,apply,function]). + +exception_meta_nocatch(doc) -> + ["Tests meta exception_trace"]; +exception_meta_nocatch(Config) when is_list(Config) -> + exception_test([meta,nocatch]). + +exception_meta_nocatch_apply(doc) -> + ["Tests meta exception_trace"]; +exception_meta_nocatch_apply(Config) when is_list(Config) -> + exception_test([meta,nocatch,apply]). + +exception_meta_nocatch_function(doc) -> + ["Tests meta exception_trace"]; +exception_meta_nocatch_function(Config) when is_list(Config) -> + exception_test([meta,nocatch,function]). + +exception_meta_nocatch_apply_function(doc) -> + ["Tests meta exception_trace"]; +exception_meta_nocatch_apply_function(Config) when is_list(Config) -> + exception_test([meta,nocatch,apply,function]). + +-endif. + + + +%%% Message patterns and expect functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-define(pCT(P,M,F,A), {trace, P,call,{M,F,A}}). +-define(pCTT(P,M,F,A), {trace_ts,P,call,{M,F,A},{_,_,_}}). +-define(pRF(P,M,F,A,V), {trace, P,return_from,{M,F,A},V}). +-define(pRFT(P,M,F,A,V),{trace_ts,P,return_from,{M,F,A},V,{_,_,_}}). +-define(pEF(P,M,F,A,V), {trace, P,exception_from,{M,F,A},V}). +-define(pEFT(P,M,F,A,V),{trace_ts,P,exception_from,{M,F,A},V,{_,_,_}}). +-define(pRT(P,M,F,A), {trace, P,return_to,{M,F,A}}). +-define(pRTT(P,M,F,A), {trace_ts,P,return_to,{M,F,A},{_,_,_}}). + +-define(CT(M,F,A), ?pCT(_,M,F,A) = receive_next()). +-define(CTT(M,F,A), ?pCTT(_,M,F,A) = receive_next()). +-define(RF(M,F,A,V), ?pRF(_,M,F,A,V) = receive_next()). +-define(RFT(M,F,A,V), ?pRFT(_,M,F,A,V) = receive_next()). +-define(EF(M,F,A,V), ?pEF(_,M,F,A,V) = receive_next()). +-define(EFT(M,F,A,V), ?pEFT(_,M,F,A,V) = receive_next()). +-define(RT(M,F,A), ?pRT(_,M,F,A) = receive_next()). +-define(RTT(M,F,A), ?pRTT(_,M,F,A) = receive_next()). +-define(NM, receive_no_next(100)). + +expect() -> + {Pid,_} = get(slave), + expect_receive(Pid). + +expect(Msg) -> + {Pid,_} = get(slave), + expect_pid(Pid, Msg). + + + +expect_pid(_Pid, []) -> + ok; +expect_pid(Pid, [Line|T]) when is_integer(Line) -> + put(test_server_loc, {?MODULE,Line}), + expect_pid(Pid, T); +expect_pid(Pid, [true|[_|_]=T]) -> + expect_pid(Pid, T); +expect_pid(Pid, [false|[_|T]]) -> + expect_pid(Pid, T); +expect_pid(Pid, [H|T]) -> + expect_pid(Pid, H), + expect_pid(Pid, T); +expect_pid(Pid, Msg) when is_tuple(Msg) -> + same(Msg, expect_receive(Pid)); +expect_pid(Pid, Fun) when is_function(Fun, 1) -> + case Fun(expect_receive(Pid)) of + next -> + expect_pid(Pid, Fun); + done -> + ok; + Other -> + expect_pid(Pid, Other) + end. + +expect_receive(Pid) when is_pid(Pid) -> + receive + Msg when is_tuple(Msg), + element(1, Msg) == trace, + element(2, Msg) =/= Pid; + %% + is_tuple(Msg), + element(1, Msg) == trace_ts, + element(2, Msg) =/= Pid -> + expect_receive(Pid); + Msg -> + expect_msg(Pid, Msg) + after 100 -> + {nm} + end. + +expect_msg(P, ?pCT(P,M,F,Args)) -> {ct,{M,F},Args}; +expect_msg(P, ?pCTT(P,M,F,Args)) -> {ctt,{M,F},Args}; +expect_msg(P, ?pRF(P,M,F,Arity,V)) -> {rf,{M,F,Arity},V}; +expect_msg(P, ?pRFT(P,M,F,Arity,V)) -> {rft,{M,F,Arity},V}; +expect_msg(P, ?pEF(P,M,F,Arity,V)) -> {ef,{M,F,Arity},V}; +expect_msg(P, ?pEFT(P,M,F,Arity,V)) -> {eft,{M,F,Arity},V}; +expect_msg(P, ?pRT(P,M,F,Arity)) -> {rt,{M,F,Arity}}; +expect_msg(P, ?pRTT(P,M,F,Arity)) -> {rtt,{M,F,Arity}}; +expect_msg(P, Msg) when is_tuple(Msg) -> + case tuple_to_list(Msg) of + [trace,P|T] -> + list_to_tuple([trace|T]); + [trace_ts,P|[_|_]=T] -> + list_to_tuple([trace_ts|reverse(tl(reverse(T)))]); + _ -> + Msg + end. + +same(A, B) -> + case [A|B] of + [X|X] -> + ok + end. + + + +%%% tests %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +basic_test() -> + ?line setup([call]), + ?line erlang:trace_pattern({?MODULE,'_','_'},[],[local]), + ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), + ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?CT(?MODULE,exported_wrap,[1]), + ?line ?CT(?MODULE,exported,[1]), + ?line ?CT(?MODULE,local,[1]), + ?line ?CT(?MODULE,local2,[1]), + ?line ?CT(?MODULE,local_tail,[1]), + ?line erlang:trace_pattern({?MODULE,'_','_'},[],[]), + ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), + ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?CT(?MODULE,exported_wrap,[1]), + ?line [1,1,1,1] = lambda_slave(fun() -> + exported_wrap(1) + end), + ?line ?NM, + ?line erlang:trace_pattern({?MODULE,'_','_'},[],[local]), + ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), + ?line [1,1,1,1] = lambda_slave(fun() -> + exported_wrap(1) + end), + ?line ?CT(?MODULE,_,_), %% The fun + ?line ?CT(?MODULE,exported_wrap,[1]), + ?line ?CT(?MODULE,exported,[1]), + ?line ?CT(?MODULE,local,[1]), + ?line ?CT(?MODULE,local2,[1]), + ?line ?CT(?MODULE,local_tail,[1]), + ?line erlang:trace_pattern({?MODULE,'_','_'},false,[local]), + ?line shutdown(), + ?line ?NM, + ok. + +%% OTP-7399. +bit_syntax_test() -> + ?line setup([call]), + ?line erlang:trace_pattern({?MODULE,'_','_'},[],[local]), + ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), + + ?line lambda_slave(fun() -> + 6 = bs_sum_a(<<1,2,3>>, 0), + 10 = bs_sum_b(0, <<1,2,3,4>>), + 26 = bs_sum_c(<<3:4,5:4,7:4,11:4>>, 0) + end), + ?line ?CT(?MODULE,_,[]), %Ignore call to the fun. + + ?line ?CT(?MODULE,bs_sum_a,[<<1,2,3>>,0]), + ?line ?CT(?MODULE,bs_sum_a,[<<2,3>>,1]), + ?line ?CT(?MODULE,bs_sum_a,[<<3>>,3]), + ?line ?CT(?MODULE,bs_sum_a,[<<>>,6]), + + ?line ?CT(?MODULE,bs_sum_b,[0,<<1,2,3,4>>]), + ?line ?CT(?MODULE,bs_sum_b,[1,<<2,3,4>>]), + ?line ?CT(?MODULE,bs_sum_b,[3,<<3,4>>]), + ?line ?CT(?MODULE,bs_sum_b,[6,<<4>>]), + ?line ?CT(?MODULE,bs_sum_b,[10,<<>>]), + + ?line ?CT(?MODULE,bs_sum_c,[<<3:4,5:4,7:4,11:4>>, 0]), + ?line ?CT(?MODULE,bs_sum_c,[<<5:4,7:4,11:4>>, 3]), + ?line ?CT(?MODULE,bs_sum_c,[<<7:4,11:4>>, 8]), + ?line ?CT(?MODULE,bs_sum_c,[<<11:4>>, 15]), + ?line ?CT(?MODULE,bs_sum_c,[<<>>, 26]), + + ?line erlang:trace_pattern({?MODULE,'_','_'},false,[local]), + ?line shutdown(), + ?line ?NM, + + ok. + +bs_sum_a(<<H,T/binary>>, Acc) -> bs_sum_a(T, H+Acc); +bs_sum_a(<<>>, Acc) -> Acc. + +bs_sum_b(Acc, <<H,T/binary>>) -> bs_sum_b(H+Acc, T); +bs_sum_b(Acc, <<>>) -> Acc. + +bs_sum_c(<<H:4,T/bits>>, Acc) -> bs_sum_c(T, H+Acc); +bs_sum_c(<<>>, Acc) -> Acc. + +return_test() -> + ?line setup([call]), + ?line erlang:trace_pattern({?MODULE,'_','_'},[{'_',[],[{return_trace}]}], + [local]), + ?line erlang:trace_pattern({erlang,hash,'_'},[{'_',[],[{return_trace}]}], + [local]), + ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), + ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?CT(?MODULE,exported_wrap,[1]), + ?line ?CT(?MODULE,exported,[1]), + ?line ?CT(?MODULE,local,[1]), + ?line ?CT(?MODULE,local2,[1]), + ?line ?CT(?MODULE,local_tail,[1]), + ?line ?CT(erlang,hash,[1,1]), + ?line ?RF(erlang,hash,2,1), + ?line ?RF(?MODULE,local_tail,1,[1,1]), + ?line ?RF(?MODULE,local2,1,[1,1]), + ?line ?RF(?MODULE,local,1,[1,1,1]), + ?line ?RF(?MODULE,exported,1,[1,1,1,1]), + ?line ?RF(?MODULE,exported_wrap,1,[1,1,1,1]), + ?line shutdown(), + ?line setup([call,return_to]), + ?line erlang:trace_pattern({?MODULE,'_','_'},[], + [local]), + ?line erlang:trace_pattern({erlang,hash,'_'},[], + [local]), + ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), + ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?CT(?MODULE,exported_wrap,[1]), + ?line ?CT(?MODULE,exported,[1]), + ?line ?CT(?MODULE,local,[1]), + ?line ?CT(?MODULE,local2,[1]), + ?line ?CT(?MODULE,local_tail,[1]), + ?line ?CT(erlang,hash,[1,1]), + ?line ?RT(?MODULE,local_tail,1), + ?line ?RT(?MODULE,local,1), + ?line ?RT(?MODULE,exported,1), + ?line ?RT(?MODULE,slave,2), + ?line shutdown(), + ?line setup([call,return_to]), + ?line erlang:trace_pattern({?MODULE,'_','_'},[{'_',[],[{return_trace}]}], + [local]), + ?line erlang:trace_pattern({erlang,hash,'_'},[{'_',[],[{return_trace}]}], + [local]), + ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), + ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?CT(?MODULE,exported_wrap,[1]), + ?line ?CT(?MODULE,exported,[1]), + ?line ?CT(?MODULE,local,[1]), + ?line ?CT(?MODULE,local2,[1]), + ?line ?CT(?MODULE,local_tail,[1]), + ?line ?CT(erlang,hash,[1,1]), + ?line ?RF(erlang,hash,2,1), + ?line ?RT(?MODULE,local_tail,1), + ?line ?RF(?MODULE,local_tail,1,[1,1]), + ?line ?RF(?MODULE,local2,1,[1,1]), + ?line ?RT(?MODULE,local,1), + ?line ?RF(?MODULE,local,1,[1,1,1]), + ?line ?RT(?MODULE,exported,1), + ?line ?RF(?MODULE,exported,1,[1,1,1,1]), + ?line ?RF(?MODULE,exported_wrap,1,[1,1,1,1]), + ?line ?RT(?MODULE,slave,2), + ?line shutdown(), + ?line ?NM, + ok. + +on_and_off_test() -> + ?line Pid = setup([call]), + ?line 1 = erlang:trace_pattern({?MODULE,local_tail,1},[],[local]), + ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), + ?line LocalTail = fun() -> + local_tail(1) + end, + ?line [1,1] = lambda_slave(LocalTail), + ?line ?CT(?MODULE,local_tail,[1]), + ?line erlang:trace(Pid,true,[return_to]), + ?line [1,1] = lambda_slave(LocalTail), + ?line ?CT(?MODULE,local_tail,[1]), + ?line ?RT(?MODULE,_,_), + ?line 0 = erlang:trace_pattern({?MODULE,local_tail,1},[],[global]), + ?line [1,1] = lambda_slave(LocalTail), + ?line ?NM, + ?line 1 = erlang:trace_pattern({?MODULE,exported_wrap,1},[],[global]), + ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?CT(?MODULE,exported_wrap,[1]), + ?line 1 = erlang:trace_pattern({?MODULE,exported_wrap,1},[],[local]), + ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?CT(?MODULE,exported_wrap,[1]), + ?line ?RT(?MODULE,slave,2), + ?line 1 = erlang:trace_pattern({erlang,hash,2},[],[local]), + ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?CT(?MODULE,exported_wrap,[1]), + ?line ?CT(erlang,hash,[1,1]), + ?line ?RT(?MODULE,local_tail,1), + ?line ?RT(?MODULE,slave,2), + ?line erlang:trace(Pid,true,[timestamp]), + ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?CTT(?MODULE,exported_wrap,[1]), + ?line ?CTT(erlang,hash,[1,1]), + ?line ?RTT(?MODULE,local_tail,1), + ?line ?RTT(?MODULE,slave,2), + ?line erlang:trace(Pid,false,[return_to,timestamp]), + ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?CT(?MODULE,exported_wrap,[1]), + ?line ?CT(erlang,hash,[1,1]), + ?line erlang:trace(Pid,true,[return_to]), + ?line 1 = erlang:trace_pattern({erlang,hash,2},[],[]), + ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?CT(?MODULE,exported_wrap,[1]), + ?line ?CT(erlang,hash,[1,1]), + ?line ?RT(?MODULE,slave,2), + ?line 1 = erlang:trace_pattern({?MODULE,exported_wrap,1},[],[]), + ?line [1,1,1,1] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?CT(?MODULE,exported_wrap,[1]), + ?line ?CT(erlang,hash,[1,1]), + ?line shutdown(), + ?line erlang:trace_pattern({'_','_','_'},false,[local]), + ?line N = erlang:trace_pattern({erlang,'_','_'},true,[local]), + ?line case erlang:trace_pattern({erlang,'_','_'},false,[local]) of + N -> + ok; + Else -> + exit({number_mismatch, {expected, N}, {got, Else}}) + end, + ?line case erlang:trace_pattern({erlang,'_','_'},false,[local]) of + N -> + ok; + Else2 -> + exit({number_mismatch, {expected, N}, {got, Else2}}) + end, + ?line M = erlang:trace_pattern({erlang,'_','_'},true,[]), + ?line case erlang:trace_pattern({erlang,'_','_'},false,[]) of + M -> + ok; + Else3 -> + exit({number_mismatch, {expected, N}, {got, Else3}}) + end, + ?line case erlang:trace_pattern({erlang,'_','_'},false,[]) of + M -> + ok; + Else4 -> + exit({number_mismatch, {expected, N}, {got, Else4}}) + end, + ?line ?NM, + ok. + + +stack_grow_test() -> + ?line setup([call,return_to]), + ?line 1 = erlang:trace_pattern({?MODULE,loop,4}, + [{'_',[],[{return_trace}]}],[local]), + ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), + ?line Num = 1 bsl 15, + ?line Fun = + fun(_F,0) -> ok; + (F,N) -> + receive _A -> + receive _B -> + receive _C -> + F(F,N-1) + end + end + end + end, + ?line apply_slave_async(?MODULE,loop,[{hej,hopp},[a,b,c],4.5,Num]), + ?line Fun(Fun,Num + 1), + ?line ?NM, + ok. + + +info_test() -> + ?line Flags1 = lists:sort([call,return_to]), + ?line Pid = setup(Flags1), + ?line Prog = [{['$1'],[{is_integer,'$1'}],[{message, false}]}, + {'_',[],[]}], + ?line erlang:trace_pattern({?MODULE,exported_wrap,1},Prog,[local]), + ?line erlang:trace_pattern({?MODULE,slave,'_'},false,[local]), + ?line Self = self(), + ?line {flags,L} = erlang:trace_info(Pid,flags), + ?line case lists:sort(L) of + Flags1 -> + ok; + Wrong1 -> + exit({bad_result, {erlang,trace_info,[Pid,flags]}, + {expected, Flags1}, {got, Wrong1}}) + end, + ?line {tracer,Tracer} = erlang:trace_info(Pid,tracer), + ?line case Tracer of + Self -> + ok; + Wrong2 -> + exit({bad_result, {erlang,trace_info,[Pid,tracer]}, + {expected, Self}, {got, Wrong2}}) + end, + ?line {traced,local} = erlang:trace_info({?MODULE,exported_wrap,1},traced), + ?line {match_spec, MS} = + erlang:trace_info({?MODULE,exported_wrap,1},match_spec), + ?line case MS of + Prog -> + ok; + Wrong3 -> + exit({bad_result, {erlang,trace_info, + [{?MODULE,exported_wrap,1}, + match_spec]}, + {expected, Prog}, {got, Wrong3}}) + end, + ?line erlang:garbage_collect(self()), + ?line receive + after 1 -> + ok + end, + ?line io:format("~p~n",[MS]), + ?line {match_spec,MS2} = + erlang:trace_info({?MODULE,exported_wrap,1},match_spec), + ?line io:format("~p~n",[MS2]), + ?line erlang:trace_pattern({?MODULE,exported_wrap,1},[],[]), + ?line {traced,global} = + erlang:trace_info({?MODULE,exported_wrap,1},traced), + ?line {match_spec,[]} = + erlang:trace_info({?MODULE,exported_wrap,1},match_spec), + ?line {traced,undefined} = + erlang:trace_info({?MODULE,exported_wrap,2},traced), + ?line {match_spec,undefined} = + erlang:trace_info({?MODULE,exported_wrap,2},match_spec), + ?line {traced,false} = erlang:trace_info({?MODULE,exported,1},traced), + ?line {match_spec,false} = + erlang:trace_info({?MODULE,exported,1},match_spec), + ?line shutdown(), + ok. + +delete_test(Config) -> + ?line Priv = ?config(priv_dir, Config), + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "trace_local_dummy"), + ?line {ok,trace_local_dummy} = c:c(File, [{outdir,Priv}]), + ?line code:purge(trace_local_dummy), + ?line code:delete(trace_local_dummy), + ?line 0 = erlang:trace_pattern({trace_local_dummy,'_','_'},true,[local]), + ?line ?NM, + ok. + + + +%%% exception_test %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +exception_test(Opts) -> + ?line {ProcFlags,PatFlags} = + case proplists:get_bool(meta, Opts) of + true -> {[timestamp],[meta]}; + false -> {[call,return_to,timestamp],[local]} + end, + ?line case proplists:get_bool(nocatch, Opts) of + false -> + ?line Exceptions = exceptions(), + ?line exception_test_setup(ProcFlags, PatFlags), + ?line lists:foreach( + fun ({Func,Args}) -> + ?line exception_test(Opts, Func, Args) + end, + Exceptions), + ?line shutdown(); + true -> + ?line Exceptions = exceptions(), + ?line lists:foreach( + fun ({Func,Args}) -> + ?line exception_test_setup( + [procs|ProcFlags], + PatFlags), + ?line exception_test(Opts, Func, Args), + ?line shutdown() + end, + Exceptions) + end, + ?line ok. + +exceptions() -> + ?line Ref = make_ref(), + ?line N = case os:type() of + vxworks -> + ?line 2000; % Limited memory on themachines, not actually + % VxWorks' fault /PaN + _ -> + ?line 200000 + end, + ?line LiL = seq(1, N-1, N), % Long Improper List + ?line LL = seq(1, N, []), % Long List + [{{erlang,exit}, [done]}, + {{erlang,error}, [1.0]}, + {{erlang,error}, [Ref,[]]}, + {{erlang,throw}, [4711]}, + {{erlang,'++'}, [[17],seventeen]}, + {{erlang,'++'}, [Ref,[125.125]]}, + {{?MODULE,match}, [ref,Ref]}, + {{?MODULE,match}, [Ref,Ref]}, + {{?MODULE,clause}, [ref,Ref]}, + {{?MODULE,clause}, [Ref,Ref]}, + {{?MODULE,id}, [4711.0]}, + {{?MODULE,undef}, [[Ref|Ref]]}, + {{?MODULE,lists_reverse}, [LiL,[]]}, + {{?MODULE,lists_reverse}, [LL,[]]}]. + +exception_test_setup(ProcFlags, PatFlags) -> + ?line Pid = setup(ProcFlags), + ?line io:format("=== exception_test_setup(~p, ~p): ~p~n", + [ProcFlags,PatFlags,Pid]), + ?line Mprog = [{'_',[],[{exception_trace}]}], + ?line erlang:trace_pattern({?MODULE,'_','_'}, Mprog, PatFlags), + ?line erlang:trace_pattern({?MODULE,slave,'_'},false,PatFlags), + ?line [1,1,1,1,1] = + [erlang:trace_pattern({erlang,F,A}, Mprog, PatFlags) + || {F,A} <- [{exit,1},{error,1},{error,2},{throw,1},{'++',2}]], + ?line 1 = erlang:trace_pattern({lists,reverse,2}, Mprog, PatFlags), + ?line ok. + +-record(exc_opts, {nocatch=false, meta=false}). + +exception_test(Opts, Func0, Args0) -> + ?line io:format("=== exception_test(~p, ~p, ~p)~n", + [Opts,Func0,abbr(Args0)]), + ?line Apply = proplists:get_bool(apply, Opts), + ?line Function = proplists:get_bool(function, Opts), + ?line Nocatch = proplists:get_bool(nocatch, Opts), + ?line Meta = proplists:get_bool(meta, Opts), + ?line ExcOpts = #exc_opts{nocatch=Nocatch,meta=Meta}, + + %% Func0 and Args0 are for the innermost call, now we will + %% wrap them in wrappers... + ?line {Func1,Args1} = + case Function of + true -> {fun exc/2,[Func0,Args0]}; + false -> {Func0,Args0} + end, + + ?line {Func,Args} = + case Apply of + true -> {{erlang,apply},[Func1,Args1]}; + false -> {Func1,Args1} + end, + + ?line R1 = exc_slave(ExcOpts, Func, Args), + ?line Stack2 = [{?MODULE,exc_top,3},{?MODULE,slave,2}], + ?line Stack3 = [{?MODULE,exc,2}|Stack2], + ?line Rs = + case x_exc_top(ExcOpts, Func, Args) of % Emulation + {crash,{Reason,Stack}}=R when is_list(Stack) -> + [R, + {crash,{Reason,Stack++Stack2}}, + {crash,{Reason,Stack++Stack3}}]; + R -> + [R] + end, + ?line exception_validate(R1, Rs), + ?line case R1 of + {crash,Crash} -> + ?line expect({trace_ts,exit,Crash}); + _ when not Meta -> + ?line expect({rtt,{?MODULE,slave,2}}); + _ -> + ok + end, + ?line expect({nm}). + +exception_validate(R1, [R2|Rs]) -> + case [R1|R2] of + [R|R] -> + ok; + [{crash,{badarg,[{lists,reverse,[L1a,L1b]}|T]}}| + {crash,{badarg,[{lists,reverse,[L2a,L2b]}|T]}}] -> + same({crash,{badarg,[{lists,reverse, + [lists:reverse(L1b, L1a),[]]}|T]}}, + {crash,{badarg,[{lists,reverse, + [lists:reverse(L2b, L2a),[]]}|T]}}); + _ when is_list(Rs), Rs =/= [] -> + exception_validate(R1, Rs) + end. + + + +%%% Tracee target functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% + +loop(D1,D2,D3,0) -> + io:format("~p~n",[[D1,D2,D3]]), + 0; +loop(D1,D2,D3,N) -> + max(N,loop(D1,D2,D3,N-1)). + +max(A, B) when A > B -> A; +max(_, B) -> B. + +exported_wrap(Val) -> + exported(Val). + +exported(Val) -> + [Val | local(Val)]. %% Non tail recursive local call + +local(Val) -> + [Val | local2(Val)]. %% Non tail recursive local call + +local2(Val) -> + local_tail(Val). %% Tail recursive call + +local_tail(Val) -> + [Val , erlang:hash(1,1)]. + + + +%%% exc_slave/3 tracee target functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% + +exc_top(ExcOpts, Func, Args) -> + case ExcOpts#exc_opts.nocatch of + false -> + try exc_jump(Func, Args) of + Value -> + {value,Value} + catch + Class:Reason -> + {Class,Reason} + end; + true -> + {value,exc_jump(Func, Args)} + end. + +%% x_* functions emulate the non-x_* ones. +%% x_* functions below x_exc_top +%% return {value,Value} or {Class,Reason}. +%% The only possible place for exception +%% is below exc/2. +x_exc_top(ExcOpts, Func, Args) -> + ?line Rtt = not ExcOpts#exc_opts.meta, + ?line expect({ctt,{?MODULE,exc_top},[ExcOpts,Func,Args]}), + ?line case x_exc_jump(ExcOpts, Func, Args) of + Result when not ExcOpts#exc_opts.nocatch -> + ?line expect([Rtt,{rtt,{?MODULE,exc_top,3}}, + ?LINE,{rft,{?MODULE,exc_top,3},Result}]), + ?line Result; + {value,_}=Result -> + + ?line expect([Rtt,{rtt,{?MODULE,exc_top,3}}, + ?LINE,{rft,{?MODULE,exc_top,3},Result}]), + ?line Result; + {exit,Reason}=CR -> + ?line expect({eft,{?MODULE,exc_top,3},CR}), + ?line {crash,Reason}; + {error,Reason}=CR -> + ?line expect({eft,{?MODULE,exc_top,3},CR}), + ?line {crash,{Reason,x_exc_stacktrace()}}; + CR -> + ?line expect({eft,{?MODULE,exc_top,3},CR}), + ?line {crash,CR} + end. + +exc_jump(Func, Args) -> + exc(Func, Args, jump). + +x_exc_jump(ExcOpts, Func, Args) -> + ?line expect({ctt,{?MODULE,exc_jump},[Func,Args]}), + ?line case x_exc(ExcOpts, Func, Args, jump) of + {value,Value}=Result -> + ?line expect({rft,{?MODULE,exc_jump,2},Value}), + ?line Result; + CR -> + ?line expect({eft,{?MODULE,exc_jump,2},CR}), + ?line CR + end. + +exc(Func, Args, jump) -> + exc(Func, Args, do); +exc(Func, Args, do) -> + exc(Func, Args). + +x_exc(ExcOpts, Func, Args, jump) -> + ?line expect({ctt,{?MODULE,exc},[Func,Args,jump]}), + ?line case x_exc(ExcOpts, Func, Args, do) of + {value,Value}=Result -> + ?line expect({rft,{?MODULE,exc,3},Value}), + ?line Result; + CR -> + ?line expect({eft,{?MODULE,exc,3},CR}), + ?line CR + end; +x_exc(ExcOpts, Func, Args, do) -> + ?line expect({ctt,{?MODULE,exc},[Func,Args,do]}), + ?line case x_exc(ExcOpts, Func, Args) of + {value,Value}=Result -> + ?line expect({rft,{?MODULE,exc,3},Value}), + ?line Result; + CR -> + ?line expect({eft,{?MODULE,exc,3},CR}), + ?line CR + end. + +exc({erlang,apply}, [{M,F},A]) -> + erlang:apply(M, F, id(A)); +exc({erlang,apply}, [F,A]) -> + erlang:apply(F, id(A)); +exc({erlang,error}, [E]) -> + erlang:error(id(E)); +exc({erlang,error}, [E,S]) -> + erlang:error(E, id(S)); +exc({erlang,exit}, [E]) -> + erlang:exit(id(E)); +exc({erlang,throw}, [E]) -> + erlang:throw(id(E)); +exc({erlang,'++'}, [A,B]) -> + erlang:'++'(A, id(B)); +exc({?MODULE,match}, [A,B]) -> + match(A, id(B)); +exc({?MODULE,clause}, [A,B]) -> + clause(A, id(B)); +exc({?MODULE,id}, [E]) -> + id(id(E)); +exc({?MODULE,undef}, [E]) -> + undef(id(E)); +exc({?MODULE,lists_reverse}, [A,B]) -> + lists_reverse(A, id(B)); +exc(Func, [A,B]) when is_function(Func, 2) -> + Func(A, id(B)). + +x_exc(ExcOpts, {erlang,apply}=Func0, [{_,_}=Func,Args]=Args0) -> + ?line expect({ctt,{?MODULE,exc},[Func0,Args0]}), + ?line x_exc_body(ExcOpts, Func, Args, true); +x_exc(ExcOpts, {erlang,apply}=Func0, [Func,Args]=Args0) + when is_function(Func, 2)-> + ?line expect({ctt,{?MODULE,exc},[Func0,Args0]}), + ?line x_exc_func(ExcOpts, Func, Args, Args); +x_exc(ExcOpts, {_,_}=Func, Args) -> + ?line expect({ctt,{?MODULE,exc},[Func,Args]}), + ?line x_exc_body(ExcOpts, Func, Args, false); +x_exc(ExcOpts, Func0, [_,Args]=Args0) + when is_function(Func0, 2) -> + ?line expect({ctt,{?MODULE,exc},[Func0,Args0]}), + ?line x_exc_func(ExcOpts, Func0, Args0, Args). + +x_exc_func(ExcOpts, Func, [Func1,Args1]=Args, Id) -> + %% Assumes the called fun =:= fun exc/2, + %% will utterly fail otherwise. + ?line Rtt = not ExcOpts#exc_opts.meta, + ?line {module,M} = erlang:fun_info(Func, module), + ?line {name,F} = erlang:fun_info(Func, name), + ?line expect([{ctt,{?MODULE,id},[Id]}, + ?LINE,{rft,{?MODULE,id,1},Id}, + ?LINE,Rtt,{rtt,{?MODULE,exc,2}}, + ?LINE,{ctt,{M,F},Args}]), + ?line case x_exc(ExcOpts, Func1, Args1) of + {value,Value}=Result -> + ?line expect([{rft,{M,F,2},Value}, + ?LINE,{rft,{?MODULE,exc,2},Value}]), + ?line Result; + CR -> + ?line expect([{eft,{M,F,2},CR}, + ?LINE,{eft,{?MODULE,exc,2},CR}]), + ?line CR + end. + +x_exc_body(ExcOpts, {M,F}=Func, Args, Apply) -> + ?line Nocatch = ExcOpts#exc_opts.nocatch, + ?line Rtt = not ExcOpts#exc_opts.meta, + ?line Id = case Apply of + true -> Args; + false -> lists:last(Args) + end, + ?line expect([{ctt,{?MODULE,id},[Id]}, + ?LINE,{rft,{?MODULE,id,1},Id}, + ?LINE,Rtt,{rtt,{?MODULE,exc,2}}, + ?LINE,{ctt,{M,F},Args}]), + ?line Arity = length(Args), + ?line try exc(Func, Args) of + Value -> + ?line x_exc_value(Rtt, M, F, Args, Arity, Value), + ?line case expect() of + {rtt,{M,F,Arity}} when Rtt, Apply -> + %% We may get the above when + %% applying a BIF. + ?line expect({rft,{?MODULE,exc,2},Value}); + {rtt,{?MODULE,exc,2}} when Rtt, not Apply -> + %% We may get the above when + %% calling a BIF. + ?line expect({rft,{?MODULE,exc,2},Value}); + {rft,{?MODULE,exc,2},Value} -> + ?line ok + end, + ?line {value,Value} + catch + Thrown when Nocatch -> + ?line CR = {error,{nocatch,Thrown}}, + ?line x_exc_exception(Rtt, M, F, Args, Arity, CR), + ?line expect({eft,{?MODULE,exc,2},CR}), + ?line CR; + Class:Reason -> + ?line CR = {Class,Reason}, + ?line x_exc_exception(Rtt, M, F, Args, Arity, CR), + ?line expect({eft,{?MODULE,exc,2},CR}), + ?line CR + end. + +x_exc_value(Rtt, ?MODULE, lists_reverse, [La,Lb], 2, R) -> + ?line L = lists:reverse(Lb, La), + ?line expect([fun ({ctt,{lists,reverse},[L1,L2]}) -> + ?line same(L, lists:reverse(L2, L1)), + ?line next; + (Msg) -> + ?line same({rft,{lists,reverse,2},R}, Msg), + ?line same(R, lists:reverse(L, [])), + ?line done + end, + ?LINE,Rtt,{rtt,{?MODULE,lists_reverse,2}}, + ?LINE,{rft,{?MODULE,lists_reverse,2},R}]); +x_exc_value(_Rtt, M, F, _, Arity, Value) -> + ?line expect({rft,{M,F,Arity},Value}). + +x_exc_exception(_Rtt, ?MODULE, lists_reverse, [La,Lb], 2, CR) -> + ?line L = lists:reverse(Lb, La), + ?line expect([fun ({ctt,{lists,reverse},[L1,L2]}) -> + ?line same(L, lists:reverse(L2, L1)), + ?line next; + (Msg) -> + ?line same({eft,{lists,reverse,2},CR}, Msg), + ?line done + end, + ?LINE,{eft,{?MODULE,lists_reverse,2},CR}]); +x_exc_exception(Rtt, ?MODULE, undef, [_], 1, {Class,Reason}=CR) -> + ?line expect([{ctt,{erlang,Class},[Reason]}, + ?LINE,{eft,{erlang,Class,1},CR}, + ?LINE,Rtt,{rtt,{error_handler,crash,1}}, + ?LINE,{eft,{?MODULE,undef,1},CR}]); +x_exc_exception(_Rtt, M, F, _, Arity, CR) -> + ?line expect({eft,{M,F,Arity},CR}). + +x_exc_stacktrace() -> + x_exc_stacktrace(erlang:get_stacktrace()). +%% Truncate stacktrace to below exc/2 +x_exc_stacktrace([{?MODULE,x_exc,4}|_]) -> []; +x_exc_stacktrace([{?MODULE,x_exc_func,4}|_]) -> []; +x_exc_stacktrace([{?MODULE,x_exc_body,4}|_]) -> []; +x_exc_stacktrace([{?MODULE,exc,2}|_]) -> []; +x_exc_stacktrace([H|T]) -> + [H|x_exc_stacktrace(T)]. + + + +match(A, B) -> + A = B. + +clause(A, A) -> + A. + +id(Id) -> + Id. + +undef(X) -> + ?MODULE:undef(X, X). % undef + +lists_reverse(A, B) -> + lists:reverse(A, B). + + + +%%% Tracee (slave) handling %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% + +slave(Dest, Sync) -> + Dest ! Sync, + receive + {From,Tag,{apply,M,F,A}} when is_pid(From) -> + ?line ?dbgformat("Apply: ~p:~p/~p (~p)~n",[M,F,length(A),A]), + ?line Res = apply(M,F,A), + ?line ?dbgformat("done Apply: ~p:~p/~p (~p)~n",[M,F,length(A),A]), + From ! {Tag,Res}, + slave(From, Tag); + {From,Tag,{lambda,Fun}} when is_pid(From) -> + Res = Fun(), + From ! {Tag,Res}, + slave(From, Tag); + {From,Tag,{exc_top,Catch,Func,Args}} when is_pid(From) -> + ?line ?dbgformat("Exc: ~p ~p~p ~n",[Catch,Func,Args]), + ?line Res = exc_top(Catch, Func, Args), + ?line ?dbgformat("done Exc: ~p ~p~p ~n",[Catch,Func,Args]), + From ! {Tag,Res}, + slave(From,Tag); + die -> + exit(normal) + end. + +setup(ProcFlags) -> + trace_off(), + flush(100), + Self = self(), + Sync = make_ref(), + Pid = spawn(fun () -> slave(Self, Sync) end), + Mref = erlang:monitor(process, Pid), + receive + Sync -> + put(slave, {Pid,Mref}), + case ProcFlags of + [] -> ok; + _ -> + erlang:trace(Pid, true, ProcFlags) + end, + Pid + end. + +shutdown() -> + trace_off(), + {Pid,Mref} = get(slave), + try erlang:is_process_alive(Pid) of + true -> + Pid ! die, + receive + {'DOWN',Mref,process,Pid,Reason} -> + Reason + end; + _ -> + not_alive + catch _:_ -> + undefined + end. + +trace_off() -> + erlang:trace_pattern({'_','_','_'},false,[]), + erlang:trace_pattern({'_','_','_'},false,[local]), + erlang:trace_pattern({'_','_','_'},false,[meta]), + erlang:trace(all, false, [all]). + + +apply_slave_async(M,F,A) -> + {Pid,Mref} = get(slave), + spawn(?MODULE,apply_slave_async,[M,F,A,Pid,Mref]), + Pid. + +apply_slave_async(M,F,A,Pid,Mref) -> + Tag = make_ref(), + Pid ! {self(),Tag,{apply,M,F,A}}, + result(Tag, Mref). + +apply_slave(M,F,A) -> + request({apply,M,F,A}). + +lambda_slave(Fun) -> + request({lambda,Fun}). + +exc_slave(Opts, Func, Args) -> + try request({exc_top,Opts,Func,Args}) + catch + Reason -> + {crash,Reason} + end. + +request(Request) -> + Tag = make_ref(), + {Pid,Mref} = get(slave), + Pid ! {self(),Tag,Request}, + result(Tag, Mref). + +result(Tag, Mref) -> + receive + {Tag,Result} -> + receive + Tag -> + Result + end; + {'DOWN',Mref,process,_Pid,Reason} -> + throw(Reason) + end. + + + +%%% Some receive helpers %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% + +receive_next() -> + receive_next(?DEFAULT_RECEIVE_TIMEOUT). + +receive_next(TO) -> + receive + M -> + M + after TO -> + ?t:fail(timeout) + end. + +receive_no_next(TO) -> + receive M -> + ?t:fail({unexpected_message,[M|flush(TO)]}) + after TO -> + ok + end. + +flush(T) -> + receive + M -> + [M|flush(T)] + after T -> + [] + end. + + + +%%% Helpers %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% + +%% Do not build garbage +%% +seq(M, N, R) when M =< N -> + seq(M, N-1, [N|R]); +seq(_, _, R) -> R. + +%% Do not call traced lists:reverse +reverse(L) -> + reverse(L, []). +%% +reverse([], R) -> R; +reverse([H|T], R) -> + reverse(T, [H|R]). + +%% Abbreviate large complex terms to avoid croaking printout +%% +abbr(Term) -> + abbr(Term, 20). +%% +abbr(Tuple, N) when is_tuple(Tuple) -> + list_to_tuple(abbr_tuple(Tuple, N, 1)); +abbr(List, N) when is_list(List) -> + abbr_list(List, N, []); +abbr(Term, _) -> Term. +%% +abbr_tuple(Tuple, N, J) when J =< size(Tuple) -> + if J > N; N =< 0 -> + ['...']; + true -> + [abbr(element(J, Tuple), N-1)|abbr_tuple(Tuple, J+1, N)] + end; +abbr_tuple(_, _, _) -> + []. +%% +abbr_list(_, 0, R) -> + case io_lib:printable_list(R) of + true -> + reverse(R, "..."); + false -> + reverse(R, '...') + end; +abbr_list([H|T], N, R) -> + M = N-1, + abbr_list(T, M, [abbr(H, M)|R]); +abbr_list(T, _, R) -> + reverse(R, T). diff --git a/erts/emulator/test/trace_local_SUITE_data/trace_local_dummy.erl b/erts/emulator/test/trace_local_SUITE_data/trace_local_dummy.erl new file mode 100644 index 0000000000..be9bea209a --- /dev/null +++ b/erts/emulator/test/trace_local_SUITE_data/trace_local_dummy.erl @@ -0,0 +1,28 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(trace_local_dummy). + +-export([dummy/0]). + +dummy() -> + dummy2(). + +dummy2() -> + hoppla. diff --git a/erts/emulator/test/trace_meta_SUITE.erl b/erts/emulator/test/trace_meta_SUITE.erl new file mode 100644 index 0000000000..d84cb3cdf2 --- /dev/null +++ b/erts/emulator/test/trace_meta_SUITE.erl @@ -0,0 +1,758 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% +%%% Define to run outside of test server +%%% +%%% -define(STANDALONE,1). +%%% +%%% +%%% Define for debug output +%%% +%%% -define(debug,1). + +-module(trace_meta_SUITE). + +%% Exported end user tests +-export([basic_test/0, return_test/0, on_and_off_test/0, stack_grow_test/0, + info_test/0, tracer_test/0, combo_test/0, nosilent_test/0]). + +%% Internal exports +-export([exported/1, exported_wrap/1, loop/4, id/1, receiver/1]). + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Test server related stuff +%% + +-ifdef(STANDALONE). +-define(config(A,B),config(A,B)). +-export([config/2]). +-else. +-include("test_server.hrl"). +-endif. + +-ifdef(debug). +-ifdef(STANDALONE). +-define(line, erlang:display({?MODULE,?LINE}), ). +-endif. +-define(dbgformat(A,B),io:format(A,B)). +-else. +-ifdef(STANDALONE). +-define(line, noop, ). +-endif. +-define(dbgformat(A,B),noop). +-endif. + +-ifdef(STANDALONE). +config(priv_dir,_) -> + ".". +-else. +%% When run in test server. +-export([all/1, init_per_testcase/2, fin_per_testcase/2, not_run/1]). +-export([basic/1, return/1, on_and_off/1, stack_grow/1, + info/1, tracer/1, combo/1, nosilent/1]). + +init_per_testcase(_Case, Config) -> + ?line Dog=test_server:timetrap(test_server:minutes(5)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) -> + shutdown(), + Dog=?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. +all(doc) -> + ["Test meta tracing of local function calls and return trace."]; +all(suite) -> + case test_server:is_native(?MODULE) of + true -> [not_run]; + false -> [basic, return, on_and_off, stack_grow, + info, tracer, combo, nosilent] + end. + +not_run(Config) when is_list(Config) -> + {skipped,"Native code"}. + +basic(suite) -> + []; +basic(doc) -> + ["Tests basic meta trace"]; +basic(Config) when is_list(Config) -> + basic_test(). + +return(suite) -> + []; +return(doc) -> + ["Tests return trace"]; +return(Config) when is_list(Config) -> + return_test(). + +on_and_off(suite) -> + []; +on_and_off(doc) -> + ["Tests turning trace parameters on and off"]; +on_and_off(Config) when is_list(Config) -> + on_and_off_test(). + +stack_grow(doc) -> + ["Tests the stack growth during return traces"]; +stack_grow(Config) when is_list(Config) -> + stack_grow_test(). + +info(doc) -> + ["Tests the trace_info BIF"]; +info(Config) when is_list(Config) -> + info_test(). + +tracer(suite) -> + []; +tracer(doc) -> + ["Tests stopping and changing tracer process"]; +tracer(Config) when is_list(Config) -> + tracer_test(). + +combo(suite) -> + []; +combo(doc) -> + ["Tests combining local call trace with meta trace"]; +combo(Config) when is_list(Config) -> + combo_test(). + +nosilent(suite) -> + []; +nosilent(doc) -> + ["Tests that meta trace is not silenced by the silent process flag"]; +nosilent(Config) when is_list(Config) -> + nosilent_test(). + +-endif. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Result examination macros + +-define(CT(P,MFA),{trace,P,call,MFA}). +-define(CTT(P, MFA),{trace_ts,P,call,MFA,{_,_,_}}). +-define(RF(P,MFA,V),{trace,P,return_from,MFA,V}). +-define(RFT(P,MFA,V),{trace_ts,P,return_from,MFA,V,{_,_,_}}). +-define(RT(P,MFA),{trace,P,return_to,MFA}). +-define(RTT(P,MFA),{trace_ts,P,return_to,MFA,{_,_,_}}). +-define(NM, receive_no_next(100)). + +%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% The Tests +%%% + +basic_test() -> + ?line Pid = setup(), + ?line erlang:trace_pattern({?MODULE,'_','_'},[],[meta]), + ?line [1,1,1,0] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?CTT(Pid,{?MODULE,exported_wrap,[1]}) = receive_next(), + ?line ?CTT(Pid,{?MODULE,exported,[1]}) = receive_next(), + ?line ?CTT(Pid,{?MODULE,local,[1]}) = receive_next(), + ?line ?CTT(Pid,{?MODULE,local2,[1]}) = receive_next(), + ?line ?CTT(Pid,{?MODULE,local_tail,[1]}) = receive_next(), + ?line erlang:trace_pattern({?MODULE,'_','_'},false,[meta]), + ?line [1,1,1,0] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?NM, + ?line [1,1,1,0] = lambda_slave(fun() -> + exported_wrap(1) + end), + ?line ?NM, + ?line erlang:trace_pattern({?MODULE,'_','_'},[],[meta]), + ?line [1,1,1,0] = lambda_slave(fun() -> + exported_wrap(1) + end), + ?line ?CTT(Pid,{?MODULE,_,_}) = receive_next(), %% The fun + ?line ?CTT(Pid,{?MODULE,exported_wrap,[1]}) = receive_next(), + ?line ?CTT(Pid,{?MODULE,exported,[1]}) = receive_next(), + ?line ?CTT(Pid,{?MODULE,local,[1]}) = receive_next(), + ?line ?CTT(Pid,{?MODULE,local2,[1]}) = receive_next(), + ?line ?CTT(Pid,{?MODULE,local_tail,[1]}) = receive_next(), + ?line erlang:trace_pattern({?MODULE,'_','_'},false,[meta]), + ?line shutdown(), + ?line ?NM, + ok. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +return_test() -> + ?line Pid = setup(), + ?line erlang:trace_pattern({?MODULE,'_','_'},[{'_',[],[{return_trace}]}], + [meta]), + ?line erlang:trace_pattern({erlang,phash2,'_'},[{'_',[],[{return_trace}]}], + [meta]), + ?line [1,1,1,0] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?CTT(Pid,{?MODULE,exported_wrap,[1]}) = receive_next(), + ?line ?CTT(Pid,{?MODULE,exported,[1]}) = receive_next(), + ?line ?CTT(Pid,{?MODULE,local,[1]}) = receive_next(), + ?line ?CTT(Pid,{?MODULE,local2,[1]}) = receive_next(), + ?line ?CTT(Pid,{?MODULE,local_tail,[1]}) = receive_next(), + ?line ?CTT(Pid,{erlang,phash2,[1,1]}) = receive_next(), + ?line ?RFT(Pid,{erlang,phash2,2},0) = receive_next(), + ?line ?RFT(Pid,{?MODULE,local_tail,1},[1,0]) = receive_next(), + ?line ?RFT(Pid,{?MODULE,local2,1},[1,0]) = receive_next(), + ?line ?RFT(Pid,{?MODULE,local,1},[1,1,0]) = receive_next(), + ?line ?RFT(Pid,{?MODULE,exported,1},[1,1,1,0]) = receive_next(), + ?line ?RFT(Pid,{?MODULE,exported_wrap,1},[1,1,1,0]) = receive_next(), + ?line shutdown(), + ?line ?NM, + ok. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +on_and_off_test() -> + ?line Pid = setup(), + ?line 1 = erlang:trace_pattern({?MODULE,local_tail,1},[],[meta]), + ?line LocalTail = fun() -> + local_tail(1) + end, + ?line [1,0] = lambda_slave(LocalTail), + ?line ?CTT(Pid,{?MODULE,local_tail,[1]}) = receive_next(), + ?line 0 = erlang:trace_pattern({?MODULE,local_tail,1},[],[global]), + ?line [1,0] = lambda_slave(LocalTail), + ?line ?NM, + ?line 1 = erlang:trace_pattern({?MODULE,exported_wrap,1},[],[meta]), + ?line [1,1,1,0] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?CTT(Pid,{?MODULE,exported_wrap,[1]}) = receive_next(), + ?line 1 = erlang:trace_pattern({erlang,phash2,2},[],[meta]), + ?line [1,1,1,0] = apply_slave(?MODULE,exported_wrap,[1]), + ?line ?CTT(Pid,{?MODULE,exported_wrap,[1]}) = receive_next(), + ?line ?CTT(Pid,{erlang,phash2,[1,1]}) = receive_next(), + ?line shutdown(), + ?line erlang:trace_pattern({'_','_','_'},false,[meta]), + ?line N = erlang:trace_pattern({erlang,'_','_'},true,[meta]), + ?line case erlang:trace_pattern({erlang,'_','_'},false,[meta]) of + N -> + ok; + Else -> + exit({number_mismatch, {expected, N}, {got, Else}}) + end, + ?line case erlang:trace_pattern({erlang,'_','_'},false,[meta]) of + N -> + ok; + Else2 -> + exit({number_mismatch, {expected, N}, {got, Else2}}) + end, + ?line ?NM, + ok. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +stack_grow_test() -> + ?line Pid = setup(), + ?line 1 = erlang:trace_pattern({?MODULE,loop,4}, + [{'_',[],[{return_trace}]}],[meta]), + ?line Num = 1 bsl 15, + ?line Surface = + fun (This, ?RFT(P,{?MODULE,loop,4},N), N) when P == Pid-> + if N == Num -> + ?NM, + ok; + true -> + This(This, receive_next(), N+1) + end + end, + ?line Dive = + fun (This, ?CTT(P,{?MODULE,loop,[{hej,hopp},[a,b,c],4.5,N]}), N) + when P == Pid-> + if N == 0 -> + Surface(Surface, receive_next(), 0); + true -> + This(This, receive_next(), N-1) + end + end, + ?line apply_slave(?MODULE,loop,[{hej,hopp},[a,b,c],4.5,Num]), +% ?line apply_slave_async(?MODULE,loop,[{hej,hopp},[a,b,c],4.5,Num]), +% ?line List = collect(test_server:seconds(5)), + ?line ok = Dive(Dive, receive_next(), Num), + ?line ?NM, + ok. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +info_test() -> + ?line setup(), + ?line Prog = [{['$1'],[{is_integer,'$1'}],[{message, false}]}, + {'_',[],[]}], + ?line Self = self(), + ?line GoOn = make_ref(), + + ?line Pid = + spawn_link( + fun () -> + erlang:trace_pattern({?MODULE,exported_wrap,1}, + Prog, [{meta, Self}]), + Self ! {self(), GoOn} + end), + ?line receive {Pid, GoOn} -> ok end, + ?line {traced,false} = erlang:trace_info({?MODULE,exported_wrap,1}, traced), + ?line {match_spec, false} = + erlang:trace_info({?MODULE,exported_wrap,1}, match_spec), + ?line {meta, Self} = erlang:trace_info({?MODULE,exported_wrap,1}, meta), + ?line {meta_match_spec, MMS} = + erlang:trace_info({?MODULE,exported_wrap,1}, meta_match_spec), + ?line case MMS of + Prog -> + ok; + Wrong -> + exit({bad_result, {erlang,trace_info, + [{?MODULE,exported_wrap,1}, + meta_match_spec]}, + {expected, Prog}, {got, Wrong}}) + end, + ?line erlang:garbage_collect(self()), + ?line receive + after 1 -> + ok + end, + ?line io:format("~p~n",[MMS]), + ?line {meta_match_spec,MMS2} = + erlang:trace_info({?MODULE,exported_wrap,1}, meta_match_spec), + ?line io:format("~p~n",[MMS2]), + ?line case MMS2 of + Prog -> + ok; + Wrong2 -> + exit({bad_result, {erlang,trace_info, + [{?MODULE,exported_wrap,1}, + meta_match_spec]}, + {expected, Prog}, {got, Wrong2}}) + end, + ?line {all, [_|_]=L} = erlang:trace_info({?MODULE,exported_wrap,1}, all), + ?line {value, {meta, Self}} = + lists:keysearch(meta, 1, L), + ?line {value, {meta_match_spec, MMS}} = + lists:keysearch(meta_match_spec, 1, L), + + ?line erlang:trace_pattern({?MODULE,exported_wrap,1}, true, [meta]), + ?line {meta_match_spec, []} = + erlang:trace_info({?MODULE,exported_wrap,1}, meta_match_spec), + + ?line erlang:trace_pattern({?MODULE,exported_wrap,1}, false, [meta]), + ?line {meta, false} = erlang:trace_info({?MODULE,exported_wrap,1}, meta), + ?line {meta_match_spec, false} = + erlang:trace_info({?MODULE,exported_wrap,1}, meta_match_spec), + ?line {all, false} = erlang:trace_info({?MODULE,exported_wrap,1}, all), + + ?line shutdown(), + ?line ?NM, + ok. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +tracer_test() -> + ?line Slave = setup(), + ?line Self = self(), + + ?line MatchSpec = [{'_',[],[{return_trace}]}], + ?line Tracer1 = spawn_link(fun () -> relay_n(3, Self) end), + ?line Setter = + spawn_link( + fun () -> + erlang:trace_pattern({?MODULE,receiver,1}, + MatchSpec, + [{meta,Tracer1}]), + erlang:trace_pattern({erlang,phash2,2}, + MatchSpec, + [{meta,Tracer1}]), + Self ! {self(), done} + end), + ?line receive {Setter, done} -> ok end, + ?line Ref = make_ref(), + ?line apply_slave_async(?MODULE, receiver, [Ref]), + ?line {Tracer1,?CTT(Slave,{?MODULE,receiver,[Ref]})} = receive_next(100), + ?line {Tracer1,?CTT(Slave,{erlang,phash2,[1,1]})} = receive_next(100), + ?line {Tracer1,?RFT(Slave,{erlang,phash2,2},0)} = receive_next(100), + %% Initiate a return_trace that will fail since the tracer just stopped + ?line Slave ! Ref, + ?line receive_no_next(100), + %% The breakpoint has not been hit since the tracer stopped + ?line {meta,Tracer1} = + erlang:trace_info({?MODULE,receiver,1}, meta), + ?line {meta_match_spec, MatchSpec} = + erlang:trace_info({?MODULE,receiver,1}, meta_match_spec), + ?line {meta,Tracer1} = + erlang:trace_info({erlang,phash2,2}, meta), + ?line {meta_match_spec, MatchSpec} = + erlang:trace_info({erlang,phash2,2}, meta_match_spec), + %% Initiate trace messages that will fail + ?line Ref2 = make_ref(), + ?line apply_slave_async(?MODULE, receiver, [Ref2]), + ?line Slave ! Ref2, + ?line receive_no_next(100), + ?line {meta,[]} = + erlang:trace_info({?MODULE,receiver,1}, meta), + ?line {meta_match_spec, MatchSpec} = + erlang:trace_info({?MODULE,receiver,1}, meta_match_spec), + ?line {meta,[]} = + erlang:trace_info({erlang,phash2,2}, meta), + ?line {meta_match_spec, MatchSpec} = + erlang:trace_info({erlang,phash2,2}, meta_match_spec), + %% Change tracer + ?line Tracer2 = spawn_link(fun () -> relay_n(4, Self) end), + ?line erlang:trace_pattern({?MODULE,receiver,1}, + MatchSpec, + [{meta,Tracer2}]), + ?line erlang:trace_pattern({erlang,phash2,2}, + MatchSpec, + [{meta,Tracer2}]), + ?line Ref3 = make_ref(), + ?line apply_slave_async(?MODULE, receiver, [Ref3]), + ?line {Tracer2,?CTT(Slave,{?MODULE,receiver,[Ref3]})} = receive_next(), + ?line {Tracer2,?CTT(Slave,{erlang,phash2,[1,1]})} = receive_next(), + ?line {Tracer2,?RFT(Slave,{erlang,phash2,2},0)} = receive_next(), + %% Change tracer between call trace and return trace + ?line Tracer3 = spawn_link(fun () -> relay_n(4, Self) end), + ?line erlang:trace_pattern({?MODULE,receiver,1}, + MatchSpec, + [{meta,Tracer3}]), + ?line erlang:trace_pattern({erlang,phash2,2}, + MatchSpec, + [{meta,Tracer3}]), + ?line Slave ! Ref3, + %% The return trace should still come from Tracer2 + ?line {Tracer2,?RFT(Slave,{?MODULE,receiver,1},Ref3)} = receive_next(), + ?line Ref4 = make_ref(), + %% Now should Tracer3 be used + ?line apply_slave_async(?MODULE, receiver, [Ref4]), + ?line Slave ! Ref4, + ?line {Tracer3,?CTT(Slave,{?MODULE,receiver,[Ref4]})} = receive_next(), + ?line {Tracer3,?CTT(Slave,{erlang,phash2,[1,1]})} = receive_next(), + ?line {Tracer3,?RFT(Slave,{erlang,phash2,2},0)} = receive_next(), + ?line {Tracer3,?RFT(Slave,{?MODULE,receiver,1},Ref4)} = receive_next(), + %% The breakpoint has not been hit since the tracer stopped + ?line {meta,Tracer3} = + erlang:trace_info({?MODULE,receiver,1}, meta), + ?line {meta_match_spec, MatchSpec} = + erlang:trace_info({?MODULE,receiver,1}, meta_match_spec), + ?line {meta,Tracer3} = + erlang:trace_info({erlang,phash2,2}, meta), + ?line {meta_match_spec, MatchSpec} = + erlang:trace_info({erlang,phash2,2}, meta_match_spec), + + ?line shutdown(), + ?line ?NM, + ok. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +combo_test() -> + ?line Slave = setup(), + ?line Self = self(), + + ?line MatchSpec = [{'_',[],[{return_trace}]}], + ?line Flags = lists:sort([call, return_to]), + ?line LocalTracer = spawn_link(fun () -> relay_n(6, Self) end), + ?line MetaTracer = spawn_link(fun () -> relay_n(4, Self) end), + ?line 1 = erlang:trace_pattern({?MODULE,receiver,1}, + MatchSpec, + [local,{meta,MetaTracer}]), + ?line 1 = erlang:trace_pattern({erlang,phash2,2}, + MatchSpec, + [local,{meta,MetaTracer}]), + ?line 1 = erlang:trace(Slave, true, + [{tracer,LocalTracer} | Flags]), + %% + ?line {all, TraceInfo1} = + erlang:trace_info({?MODULE,receiver,1}, all), + ?line {meta,MetaTracer} = + erlang:trace_info({?MODULE,receiver,1}, meta), + ?line {value,{meta,MetaTracer}} = + lists:keysearch(meta, 1, TraceInfo1), + ?line {meta_match_spec,MatchSpec} = + erlang:trace_info({?MODULE,receiver,1}, meta_match_spec), + ?line {value,{meta_match_spec,MatchSpec}} = + lists:keysearch(meta_match_spec, 1, TraceInfo1), + ?line {traced,local} = + erlang:trace_info({?MODULE,receiver,1}, traced), + ?line {value,{traced,local}} = + lists:keysearch(traced, 1, TraceInfo1), + ?line {match_spec,MatchSpec} = + erlang:trace_info({?MODULE,receiver,1}, match_spec), + ?line {value,{match_spec,MatchSpec}} = + lists:keysearch(match_spec, 1, TraceInfo1), + %% + ?line {all, TraceInfo2} = + erlang:trace_info({erlang,phash2,2}, all), + ?line {meta,MetaTracer} = + erlang:trace_info({erlang,phash2,2}, meta), + ?line {value,{meta,MetaTracer}} = + lists:keysearch(meta, 1, TraceInfo2), + ?line {meta_match_spec,MatchSpec} = + erlang:trace_info({erlang,phash2,2}, meta_match_spec), + ?line {value,{meta_match_spec,MatchSpec}} = + lists:keysearch(meta_match_spec, 1, TraceInfo2), + ?line {traced,local} = + erlang:trace_info({erlang,phash2,2}, traced), + ?line {value,{traced,local}} = + lists:keysearch(traced, 1, TraceInfo2), + ?line {match_spec,MatchSpec} = + erlang:trace_info({erlang,phash2,2}, match_spec), + ?line {value,{match_spec,MatchSpec}} = + lists:keysearch(match_spec, 1, TraceInfo2), + %% + ?line {flags,Flags1} = erlang:trace_info(Slave, flags), + ?line Flags = lists:sort(Flags1), + ?line {tracer,LocalTracer} = erlang:trace_info(Slave, tracer), + %% + ?line Ref = make_ref(), + ?line apply_slave_async(?MODULE, receiver, [Ref]), + ?line Slave ! Ref, + ?line ?CTT(Slave,{?MODULE,receiver,[Ref]}) = receive_next_bytag(MetaTracer), + ?line ?CTT(Slave,{erlang,phash2,[1,1]}) = receive_next_bytag(MetaTracer), + ?line ?RFT(Slave,{erlang,phash2,2},0) = receive_next_bytag(MetaTracer), + ?line ?RFT(Slave,{?MODULE,receiver,1},Ref) = receive_next_bytag(MetaTracer), + ?line ?CT(Slave,{?MODULE,receiver,[Ref]}) = receive_next_bytag(LocalTracer), + ?line ?CT(Slave,{erlang,phash2,[1,1]}) = receive_next_bytag(LocalTracer), + ?line case {receive_next_bytag(LocalTracer), + receive_next_bytag(LocalTracer)} of + {?RF(Slave,{erlang,phash2,2},0), + ?RT(Slave,{?MODULE,receiver,1})} -> + ?line ok; + {?RT(Slave,{?MODULE,receiver,1}), + ?RF(Slave,{erlang,phash2,2},0)} -> + ?line ok; + Error1 -> ?t:fail({unexpected_message, Error1}) + end, + ?line case {receive_next_bytag(LocalTracer), + receive_next_bytag(LocalTracer)} of + {?RF(Slave,{?MODULE,receiver,1},Ref), + ?RT(Slave,{?MODULE,slave,1})} -> + ?line ok; + {?RT(Slave,{?MODULE,slave,1}), + ?RF(Slave,{?MODULE,receiver,1},Ref)} -> + ?line ok; + Error2 -> ?t:fail({unexpected_message, Error2}) + end, + + ?line shutdown(), + ?line ?NM, + ok. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Use case for Inviso meta tracing: +%% Setup silent local call tracing, and start it using meta trace. + +nosilent_test() -> + ?line Pid = setup(), + ?line Trigger = {?MODULE,id,1}, + ?line TriggerMS = [{[start],[],[{silent,false}]}, + {[stop],[],[{silent,true},{return_trace}]}], + ?line 1 = erlang:trace(Pid, true, [call,silent,return_to]), + ?line erlang:trace_pattern({?MODULE,'_','_'},[],[local]), + ?line 1 = erlang:trace_pattern({?MODULE,local2,1}, + [{'_',[],[{return_trace}]}], + [local]), + ?line 1 = erlang:trace_pattern({?MODULE,slave,1},false,[local]), + ?line 1 = erlang:trace_pattern(Trigger,false,[local]), + ?line 1 = erlang:trace_pattern(Trigger,TriggerMS,[meta]), + ?line [1,1,1,0] = apply_slave(?MODULE,exported_wrap,[1]), + ?line receive_no_next(17), + ?line start = apply_slave(?MODULE, id, [start]), + ?line ?CTT(Pid,{?MODULE,id,[start]}) = receive_next(), + ?line [2,2,2,0] = apply_slave(?MODULE,exported_wrap,[2]), + ?line ?CT(Pid,{?MODULE,exported_wrap,[2]}) = receive_next(), + ?line ?CT(Pid,{?MODULE,exported,[2]}) = receive_next(), + ?line ?CT(Pid,{?MODULE,local,[2]}) = receive_next(), + ?line ?CT(Pid,{?MODULE,local2,[2]}) = receive_next(), + ?line ?CT(Pid,{?MODULE,local_tail,[2]}) = receive_next(), + ?line ?RF(Pid,{?MODULE,local2,1}, [2,0]) = receive_next(), + ?line ?RT(Pid,{?MODULE,local,1}) = receive_next(), + ?line ?RT(Pid,{?MODULE,exported,1}) = receive_next(), + ?line ?RT(Pid,{?MODULE,slave,1}) = receive_next(), + ?line stop = apply_slave(?MODULE, id, [stop]), + ?line ?CTT(Pid,{?MODULE,id,[stop]}) = receive_next(), + ?line ?RFT(Pid,{?MODULE,id,1}, stop) = receive_next(), + ?line [3,3,3,0] = apply_slave(?MODULE,exported_wrap,[3]), + ?line receive_no_next(17), + ?line shutdown(), + ok. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Trace target functions + +loop(D1,D2,D3,0) -> + io:format("~p~n",[[D1,D2,D3]]), + 0; +loop(D1,D2,D3,N) -> + max(N,loop(D1,D2,D3,N-1)). + +max(A,B) when A > B -> + A; +max(_A,B) -> + B. + +id(X) -> + X. + + +exported_wrap(Val) -> + exported(Val). + +exported(Val) -> + [Val | local(Val)]. %% Non tail recursive local call + +local(Val) -> + [Val | local2(Val)]. %% Non tail recursive local call + +local2(Val) -> + local_tail(Val). %% Tail recursive call + +local_tail(Val) -> + [Val , erlang:phash2(1,1)]. + + + +receiver(Msg) -> + erlang:phash2(1,1), + receive Msg -> Msg end. + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Trace target process and utilities + +slave(Sync) -> + Sync ! sync, + receive + {From,apply, M, F, A} -> + ?line ?dbgformat("Apply: ~p:~p/~p (~p)~n",[M,F,length(A),A]), + ?line Res = apply(M,F,A), + ?line ?dbgformat("done Apply: ~p:~p/~p (~p)~n",[M,F,length(A),A]), + From ! {apply, Res}, + erlang:trace_pattern({?MODULE,slave,1},false,[meta]), + slave(From); + {From, lambda, Fun} -> + Res = Fun(), + From ! {lambda, Res}, + erlang:trace_pattern({?MODULE,slave,1},false,[meta]), + slave(From); + die -> + exit(normal) + end. + +setup() -> + trace_off(), + Self = self(), + Pid = spawn(fun () -> slave(Self) end), + receive sync -> ok end, + put(slave,Pid), + Pid. + +shutdown() -> + trace_off(), + Pid = get(slave), + case (catch is_process_alive(Pid)) of + true -> + Ref = erlang:monitor(process,Pid), + Pid ! die, + receive + {'DOWN',Ref,process,Pid,_} -> + ok + end; + _ -> + ok + end. + +trace_off() -> + erlang:trace(all, false, [all]), + erlang:trace_pattern({'_','_','_'},false,[]), + erlang:trace_pattern({'_','_','_'},false,[local]), + erlang:trace_pattern({'_','_','_'},false,[meta]), + erlang:trace_pattern(on_load,false,[]), + erlang:trace_pattern(on_load,false,[local]), + erlang:trace_pattern(on_load,false,[meta]), + ok. + +apply_slave_async(M,F,A) -> + Slave = get(slave), + Pid = + spawn( + fun () -> + Slave ! {self(),apply, M, F, A}, + receive + {apply, _} -> + receive + sync -> + ok + end + end + end), + Pid. + +apply_slave(M,F,A) -> + Pid = get(slave), + Pid ! {self(),apply, M, F, A}, + receive + {apply, Res} -> + receive + sync -> + Res + end + end. + +lambda_slave(Fun) -> + Pid = get(slave), + Pid ! {self(), lambda, Fun}, + receive + {lambda, Res} -> + receive + sync -> + Res + end + end. + +relay_n(0, _) -> + ok; +relay_n(N, Dest) -> + receive Msg -> + Dest ! {self(), Msg}, + relay_n(N-1, Dest) + end. + + +receive_next() -> + receive_next(infinity). + +receive_next(TO) -> + receive + M -> + M + after TO -> + ?t:fail(timeout) + end. + +receive_no_next(TO) -> + receive + M -> + ?t:fail({unexpected_message, M}) + after + TO -> + ok + end. + +receive_next_bytag(Tag) -> + receive_next_bytag(Tag, infinity). +receive_next_bytag(Tag, TO) -> + receive + {Tag, Msg} -> + Msg + after + TO -> + timeout + end. diff --git a/erts/emulator/test/trace_nif_SUITE.erl b/erts/emulator/test/trace_nif_SUITE.erl new file mode 100644 index 0000000000..587cc08979 --- /dev/null +++ b/erts/emulator/test/trace_nif_SUITE.erl @@ -0,0 +1,292 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(trace_nif_SUITE). + +-include("test_server.hrl"). + +-export([all/1]). +-export([trace_nif/1, + trace_nif_timestamp/1, + trace_nif_local/1, + trace_nif_meta/1, + trace_nif_timestamp_local/1, + trace_nif_return/1, + not_run/1]). + +-export([nif_process/0, nif/0, nif/1]). + +all(suite) -> + case test_server:is_native(?MODULE) of + true -> [not_run]; + false -> + [trace_nif, + trace_nif_timestamp, + trace_nif_local, + trace_nif_meta, + trace_nif_timestamp_local, + trace_nif_return + ] + end. + +not_run(Config) when is_list(Config) -> + {skipped,"Native code"}. + +trace_nif(doc) -> "Test tracing NIFs."; +trace_nif(Config) when is_list(Config) -> + load_nif(Config), + + do_trace_nif([]). + +trace_nif_local(doc) -> "Test tracing NIFs with local flag."; +trace_nif_local(Config) when is_list(Config) -> + load_nif(Config), + do_trace_nif([local]). + +trace_nif_meta(doc) -> "Test tracing NIFs with meta flag."; +trace_nif_meta(Config) when is_list(Config) -> + load_nif(Config), + ?line Pid=spawn_link(?MODULE, nif_process, []), + ?line erlang:trace_pattern({?MODULE,nif,'_'}, [], [meta]), + + ?line Pid ! {apply_nif, nif, []}, + ?line receive_trace_msg_ts({trace_ts,Pid,call,{?MODULE,nif,[]}}), + + ?line Pid ! {apply_nif, nif, ["Arg1"]}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {?MODULE,nif, ["Arg1"]}}), + + ?line Pid ! {call_nif, nif, []}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {?MODULE,nif, []}}), + + ?line Pid ! {call_nif, nif, ["Arg1"]}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {?MODULE,nif, ["Arg1"]}}), + ok. +do_trace_nif(Flags) -> + ?line Pid = spawn(?MODULE, nif_process, []), + ?line 1 = erlang:trace(Pid, true, [call]), + ?line erlang:trace_pattern({?MODULE,nif,'_'}, [], Flags), + ?line Pid ! {apply_nif, nif, []}, + ?line receive_trace_msg({trace,Pid,call,{?MODULE,nif, []}}), + ?line Pid ! {apply_nif, nif, ["Arg1"]}, + ?line receive_trace_msg({trace,Pid,call,{?MODULE,nif, ["Arg1"]}}), + + ?line Pid ! {call_nif, nif, []}, + ?line receive_trace_msg({trace, Pid, call, {?MODULE,nif, []}}), + + ?line Pid ! {call_nif, nif, ["Arg1"]}, + ?line receive_trace_msg({trace, Pid, call, {?MODULE,nif, ["Arg1"]}}), + + + %% Switch off + ?line 1 = erlang:trace(Pid, false, [call]), + + ?line Pid ! {apply_nif, nif, []}, + receive_nothing(), + ?line Pid ! {apply_nif, nif, ["Arg1"]}, + receive_nothing(), + ?line Pid ! {call_nif, nif, []}, + receive_nothing(), + ?line Pid ! {call_nif, nif, ["Arg1"]}, + receive_nothing(), + + %% Switch on again + ?line 1 = erlang:trace(Pid, true, [call]), + ?line erlang:trace_pattern({?MODULE,nif,'_'}, [], Flags), + ?line Pid ! {apply_nif, nif, []}, + ?line receive_trace_msg({trace,Pid,call,{?MODULE,nif, []}}), + ?line Pid ! {apply_nif, nif, ["Arg1"]}, + ?line receive_trace_msg({trace,Pid,call,{?MODULE,nif, ["Arg1"]}}), + + ?line Pid ! {call_nif, nif, []}, + ?line receive_trace_msg({trace, Pid, call, {?MODULE,nif, []}}), + + ?line Pid ! {call_nif, nif, ["Arg1"]}, + ?line receive_trace_msg({trace, Pid, call, {?MODULE,nif, ["Arg1"]}}), + + ?line 1 = erlang:trace(Pid, false, [call]), + ?line erlang:trace_pattern({?MODULE,nif,'_'}, false, Flags), + ?line exit(Pid, die), + ok. + +trace_nif_timestamp(doc) -> "Test tracing NIFs with timestamps."; +trace_nif_timestamp(Config) when is_list(Config) -> + load_nif(Config), + do_trace_nif_timestamp([]). + +trace_nif_timestamp_local(doc) -> + "Test tracing NIFs with timestamps and local flag."; +trace_nif_timestamp_local(Config) when is_list(Config) -> + load_nif(Config), + do_trace_nif_timestamp([local]). + +do_trace_nif_timestamp(Flags) -> + ?line Pid=spawn(?MODULE, nif_process, []), + ?line 1 = erlang:trace(Pid, true, [call,timestamp]), + ?line erlang:trace_pattern({?MODULE,nif,'_'}, [], Flags), + + ?line Pid ! {apply_nif, nif, []}, + ?line receive_trace_msg_ts({trace_ts,Pid,call,{?MODULE,nif,[]}}), + + ?line Pid ! {apply_nif, nif, ["Arg1"]}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {?MODULE,nif, ["Arg1"]}}), + + ?line Pid ! {call_nif, nif, []}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {?MODULE,nif, []}}), + + ?line Pid ! {call_nif, nif, ["Arg1"]}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {?MODULE,nif, ["Arg1"]}}), + + %% We should be able to turn off the timestamp. + ?line 1 = erlang:trace(Pid, false, [timestamp]), + + ?line Pid ! {call_nif, nif, []}, + ?line receive_trace_msg({trace,Pid,call, + {?MODULE,nif, []}}), + + ?line Pid ! {apply_nif, nif, ["tjoho"]}, + ?line receive_trace_msg({trace,Pid,call, + {?MODULE,nif, ["tjoho"]}}), + + ?line 1 = erlang:trace(Pid, false, [call]), + ?line erlang:trace_pattern({erlang,'_','_'}, false, Flags), + + ?line exit(Pid, die), + ok. + +trace_nif_return(doc) -> + "Test tracing NIF's with return/return_to trace."; +trace_nif_return(Config) when is_list(Config) -> + load_nif(Config), + + ?line Pid=spawn(?MODULE, nif_process, []), + ?line 1 = erlang:trace(Pid, true, [call,timestamp,return_to]), + ?line erlang:trace_pattern({?MODULE,nif,'_'}, [{'_',[],[{return_trace}]}], + [local]), + + ?line Pid ! {apply_nif, nif, []}, + ?line receive_trace_msg_ts({trace_ts,Pid,call,{?MODULE,nif,[]}}), + ?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from, + {?MODULE,nif,0}}), + ?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to, + {?MODULE, nif_process,0}}), + + ?line Pid ! {call_nif, nif, ["Arg1"]}, + ?line receive_trace_msg_ts({trace_ts,Pid,call, + {?MODULE,nif, ["Arg1"]}}), + ?line receive_trace_msg_ts_return_from({trace_ts,Pid,return_from, + {?MODULE,nif,1}}), + ?line receive_trace_msg_ts_return_to({trace_ts,Pid,return_to, + {?MODULE, nif_process,0}}), + ok. + + +receive_trace_msg(Mess) -> + receive + Mess -> + ok; + Other -> + io:format("Expected: ~p,~nGot: ~p~n", [Mess, Other]), + ?t:fail() + after 5000 -> + io:format("Expected: ~p,~nGot: timeout~n", [Mess]), + ?t:fail() + end. + +receive_nothing() -> + ?line timeout = receive M -> M after 100 -> timeout end. + +receive_trace_msg_ts({trace_ts, Pid, call, {M,F,A}}) -> + receive + {trace_ts, Pid, call, {M, F, A}, _Ts} -> + ok; + Other -> + io:format("Expected: {trace, ~p, call, {~p, ~p, ~p}, TimeStamp}},~n" + "Got: ~p~n", + [Pid, M, F, A, Other]), + ?t:fail() + after 5000 -> + io:format("Got timeout~n", []), + ?t:fail() + end. + +receive_trace_msg_ts_return_from({trace_ts, Pid, return_from, {M,F,A}}) -> + receive + {trace_ts, Pid, return_from, {M, F, A}, _Value, _Ts} -> + ok; + Other -> + io:format("Expected: {trace_ts, ~p, return_from, {~p, ~p, ~p}, Value, TimeStamp}},~n" + "Got: ~p~n", + [Pid, M, F, A, Other]), + ?t:fail() + after 5000 -> + io:format("Got timeout~n", []), + ?t:fail() + end. + +receive_trace_msg_ts_return_to({trace_ts, Pid, return_to, {M,F,A}}) -> + receive + {trace_ts, Pid, return_to, {M, F, A}, _Ts} -> + ok; + Other -> + io:format("Expected: {trace_ts, ~p, return_to, {~p, ~p, ~p}, TimeStamp}},~n" + "Got: ~p~n", + [Pid, M, F, A, Other]), + ?t:fail() + after 5000 -> + io:format("Got timeout~n", []), + ?t:fail() + end. + +nif_process() -> + receive + {apply_nif, Name, Args} -> + ?line {ok,Args} = apply(?MODULE, Name, Args); + + {call_nif, Name, []} -> + ?line {ok, []} = ?MODULE:Name(); + + {call_nif, Name, [A1]} -> + ?line {ok, [A1]} = ?MODULE:Name(A1); + + {call_nif, Name, [A1,A2]} -> + ?line {ok,[A1,A2]} = ?MODULE:Name(A1,A2); + + {call_nif, Name, [A1,A2,A3]} -> + ?line {ok,[A1,A2,A3]} = ?MODULE:Name(A1,A2,A3) + end, + nif_process(). + +load_nif(Config) -> + ?line Path = ?config(data_dir, Config), + + ?line ok = erlang:load_nif(filename:join(Path,"trace_nif"), 0). + + +nif() -> + {"Stub0",[]}. %exit("nif/0 stub called"). + +nif(A1) -> + {"Stub1",[A1]}. %exit(["nif/1 stub called",A1]). + diff --git a/erts/emulator/test/trace_nif_SUITE_data/Makefile.src b/erts/emulator/test/trace_nif_SUITE_data/Makefile.src new file mode 100644 index 0000000000..26b1b58f70 --- /dev/null +++ b/erts/emulator/test/trace_nif_SUITE_data/Makefile.src @@ -0,0 +1,7 @@ + +NIF_LIBS = trace_nif@dll@ + +all: $(NIF_LIBS) + +@SHLIB_RULES@ + diff --git a/erts/emulator/test/trace_nif_SUITE_data/trace_nif.c b/erts/emulator/test/trace_nif_SUITE_data/trace_nif.c new file mode 100644 index 0000000000..732f1010ae --- /dev/null +++ b/erts/emulator/test/trace_nif_SUITE_data/trace_nif.c @@ -0,0 +1,46 @@ +#include "erl_nif.h" + + +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + return 0; +} + +static int reload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + return 0; +} + +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info) +{ + return 0; +} + +static void unload(ErlNifEnv* env, void* priv_data) +{ +} + +static ERL_NIF_TERM nif_0(ErlNifEnv* env) +{ + return enif_make_tuple(env,2, + enif_make_atom(env,"ok"), + enif_make_list(env,0)); +} + +static ERL_NIF_TERM nif_1(ErlNifEnv* env, ERL_NIF_TERM a1) +{ + return enif_make_tuple(env,2, + enif_make_atom(env,"ok"), + enif_make_list(env,1,a1)); +} + + + +static ErlNifFunc nif_funcs[] = +{ + {"nif", 0, nif_0}, + {"nif", 1, nif_1} +}; + +ERL_NIF_INIT(trace_nif_SUITE,nif_funcs,load,reload,upgrade,unload) + diff --git a/erts/emulator/test/trace_port_SUITE.erl b/erts/emulator/test/trace_port_SUITE.erl new file mode 100644 index 0000000000..5febe177f9 --- /dev/null +++ b/erts/emulator/test/trace_port_SUITE.erl @@ -0,0 +1,686 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + + +-module(trace_port_SUITE). + +-export([all/1,init_per_testcase/2,fin_per_testcase/2, + call_trace/1, + return_trace/1, + send/1, + receive_trace/1, + process_events/1, + schedule/1, + fake_schedule/1, + fake_schedule_after_register/1, + fake_schedule_after_getting_linked/1, + fake_schedule_after_getting_unlinked/1, + gc/1, + default_tracer/1]). + +-include("test_server.hrl"). + +test_cases() -> + [call_trace, + return_trace, + send, + receive_trace, + process_events, + schedule, + fake_schedule, + fake_schedule_after_register, + fake_schedule_after_getting_linked, + fake_schedule_after_getting_unlinked, + gc, + default_tracer]. + +all(suite) -> test_cases(). + +init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> + Dog = ?t:timetrap(?t:seconds(30)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +call_trace(doc) -> "Test sending call trace messages to a port."; +call_trace(Config) when is_list(Config) -> + case test_server:is_native(?MODULE) of + true -> + {skip,"Native code"}; + false -> + ?line start_tracer(Config), + Self = self(), + ?line trace_func({lists,reverse,1}, []), + ?line trace_pid(Self, true, [call]), + ?line trace_info(Self, flags), + ?line trace_info(Self, tracer), + ?line [b,a] = lists:reverse([a,b]), + ?line expect({trace,Self,call,{lists,reverse,[[a,b]]}}), + + ?line trace_pid(Self, true, [timestamp]), + ?line trace_info(Self, flags), + ?line Huge = huge_data(), + ?line lists:reverse(Huge), + ?line expect({trace_ts,Self,call,{lists,reverse,[Huge]},ts}), + + ?line trace_pid(Self, true, [arity]), + ?line trace_info(Self, flags), + ?line [y,x] = lists:reverse([x,y]), + ?line expect({trace_ts,Self,call,{lists,reverse,1},ts}), + + ?line trace_pid(Self, false, [timestamp]), + ?line trace_info(Self, flags), + ?line [z,y,x] = lists:reverse([x,y,z]), + ?line expect({trace,Self,call,{lists,reverse,1}}), + + %% OTP-7399. Delayed sub-binary creation optimization. + ?line trace_pid(Self, false, [arity]), + ?line trace_info(Self, flags), + ?line trace_func({?MODULE,bs_sum_c,2}, [], [local]), + ?line 26 = bs_sum_c(<<3:4,5:4,7:4,11:4>>, 0), + ?line trace_func({?MODULE,bs_sum_c,2}, false, [local]), + ?line expect({trace,Self,call,{?MODULE,bs_sum_c,[<<3:4,5:4,7:4,11:4>>,0]}}), + ?line expect({trace,Self,call,{?MODULE,bs_sum_c,[<<5:4,7:4,11:4>>,3]}}), + ?line expect({trace,Self,call,{?MODULE,bs_sum_c,[<<7:4,11:4>>,8]}}), + ?line expect({trace,Self,call,{?MODULE,bs_sum_c,[<<11:4>>,15]}}), + ?line expect({trace,Self,call,{?MODULE,bs_sum_c,[<<>>,26]}}), + + ?line trace_func({lists,reverse,1}, false), + ok + end. + +bs_sum_c(<<H:4,T/bits>>, Acc) -> bs_sum_c(T, H+Acc); +bs_sum_c(<<>>, Acc) -> Acc. + + +return_trace(doc) -> "Test the new return trace."; +return_trace(Config) when is_list(Config) -> + case test_server:is_native(?MODULE) of + true -> + {skip,"Native code"}; + false -> + ?line start_tracer(Config), + Self = self(), + MFA = {lists,reverse,1}, + + %% Plain (no timestamp, small data). + + ?line trace_func(MFA, [{['$1'],[],[{return_trace}, + {message,false}]}]), + ?line trace_pid(Self, true, [call]), + ?line trace_info(Self, flags), + ?line trace_info(Self, tracer), + ?line trace_info(MFA, match_spec), + ?line {traced,global} = trace_info(MFA, traced), + ?line [b,a] = lists:reverse([a,b]), + ?line expect({trace,Self,return_from,MFA,[b,a]}), + + %% Timestamp, huge data. + ?line trace_pid(Self, true, [timestamp]), + ?line Result = lists:reverse(huge_data()), + ?line expect({trace_ts,Self,return_from,MFA,Result,ts}), + + %% Turn off trace. + ?line trace_func(MFA, false), + ?line trace_info(MFA, match_spec), + ?line {traced,false} = trace_info(MFA, traced), + ok + end. + +send(doc) -> "Test sending send trace messages to a port."; +send(Config) when is_list(Config) -> + ?line Tracer = start_tracer(Config), + Self = self(), + ?line Sender = fun_spawn(fun sender/0), + ?line trac(Sender, true, [send]), + + %% Simple message, no timestamp. + + ?line Bin = list_to_binary(lists:seq(1, 10)), + ?line Msg = {some_data,Bin}, + Sender ! {send_please,self(),Msg}, + receive Msg -> ok end, + ?line expect({trace,Sender,send,Msg,Self}), + + %% Timestamp. + + BiggerMsg = {even_bigger,Msg}, + ?line trac(Sender, true, [send,timestamp]), + Sender ! {send_please,self(),BiggerMsg}, + receive BiggerMsg -> ok end, + ?line expect({trace_ts,Sender,send,BiggerMsg,Self,ts}), + + %% Huge message. + + ?line HugeMsg = huge_data(), + Sender ! {send_please,self(),HugeMsg}, + receive HugeMsg -> ok end, + ?line expect({trace_ts,Sender,send,HugeMsg,Self,ts}), + + %% Kill trace port and force a trace. The emulator should not crasch. + + ?line unlink(Tracer), + ?line exit(Tracer, kill), + erlang:yield(), % Make sure that port gets killed. + Sender ! {send_please,Self,good_bye}, + receive good_bye -> ok end, + ok. + +receive_trace(doc) -> "Test sending receive traces to a port."; +receive_trace(Config) when is_list(Config) -> + ?line start_tracer(Config), + ?line Receiver = fun_spawn(fun receiver/0), + ?line trac(Receiver, true, ['receive']), + + Receiver ! {hello,world}, + ?line expect({trace,Receiver,'receive',{hello,world}}), + + ?line trac(Receiver, true, ['receive',timestamp]), + Huge = {hello,huge_data()}, + Receiver ! {hello,huge_data()}, + ?line expect({trace_ts,Receiver,'receive',Huge,ts}), + ok. + +process_events(doc) -> "Tests a few process events (like getting linked)."; +process_events(Config) when is_list(Config) -> + ?line start_tracer(Config), + Self = self(), + ?line Receiver = fun_spawn(fun receiver/0), + ?line trac(Receiver, true, [procs]), + + unlink(Receiver), %It is already linked. + ?line expect({trace,Receiver,getting_unlinked,Self}), + link(Receiver), + ?line expect({trace,Receiver,getting_linked,Self}), + ?line trac(Receiver, true, [procs,timestamp]), + unlink(Receiver), + ?line expect({trace_ts,Receiver,getting_unlinked,Self,ts}), + link(Receiver), + ?line expect({trace_ts,Receiver,getting_linked,Self,ts}), + + unlink(Receiver), + ?line expect({trace_ts,Receiver,getting_unlinked,Self,ts}), + Huge = huge_data(), + exit(Receiver, Huge), + ?line expect({trace_ts,Receiver,exit,Huge,ts}), + + ok. + +schedule(doc) -> "Test sending scheduling events to a port."; +schedule(Config) when is_list(Config) -> + ?line start_tracer(Config), + ?line Receiver = fun_spawn(fun receiver/0), + ?line trac(Receiver, true, [running]), + + Receiver ! hi, + expect({trace,Receiver,in,{?MODULE,receiver,0}}), + expect({trace,Receiver,out,{?MODULE,receiver,0}}), + + ?line trac(Receiver, true, [running,timestamp]), + + Receiver ! hi_again, + expect({trace_ts,Receiver,in,{?MODULE,receiver,0},ts}), + expect({trace_ts,Receiver,out,{?MODULE,receiver,0},ts}), + + ok. + +run_fake_sched_test(Fun, Config) when is_function(Fun), is_list(Config) -> + ?line case catch erlang:system_info(smp_support) of + true -> + ?line {skipped, + "No need for faked schedule out/in trace messages " + "when smp support is enabled"}; + _ -> + ?line Fun(Config) + end. + +fake_schedule(doc) -> "Tests time compensating fake out/in scheduling."; +fake_schedule(Config) when is_list(Config) -> + ?line run_fake_sched_test(fun fake_schedule_test/1, Config). + +fake_schedule_test(Config) when is_list(Config) -> + ?line Tracer = start_tracer(Config), + ?line Port = get(tracer_port), + ?line General = fun_spawn(fun general/0), + %% + ?line trac(General, true, [send, running]), + %% + %% Test that fake out/in scheduling is not generated unless + %% both 'running' and 'timestamp' is active. + ?line [] = erlang:port_control(Port, $h, []), + ?line General ! nop, + ?line expect({trace, General, in, {?MODULE, general, 0}}), + ?line expect({trace, General, out, {?MODULE, general, 0}}), + ?line expect(), + %% + ?line trac(General, false, [running]), + ?line trac(General, true, [timestamp]), + %% + ?line Ref1 = make_ref(), + ?line Msg1 = {Port, {data, term_to_binary(Ref1)}}, + ?line [] = erlang:port_control(Port, $h, []), + ?line General ! {send, Tracer, Msg1}, + ?line expect({trace_ts, General, send, Msg1, Tracer, ts}), + ?line expect(Ref1), + ?line expect(), + %% + ?line trac(General, true, [running]), + %% + %% Test that fake out/in scheduling can be generated by the driver + ?line Ref2 = make_ref(), + ?line Msg2 = {Port, {data, term_to_binary(Ref2)}}, + ?line [] = erlang:port_control(Port, $h, []), + ?line General ! {send, Tracer, Msg2}, + ?line {_,_,_,_,Ts} = + expect({trace_ts, General, in, {?MODULE, general, 0}, ts}), + ?line expect({trace_ts, General, out, 0, Ts}), + ?line expect({trace_ts, General, in, 0, ts}), + ?line expect({trace_ts, General, send, Msg2, Tracer, ts}), + ?line expect(Ref2), + ?line expect({trace_ts, General, out, {?MODULE, general, 0}, ts}), + ?line expect(), + %% + %% Test that fake out/in scheduling is not generated after an + %% 'out' scheduling event + ?line Ref3 = make_ref(), + ?line Msg3 = {Port, {data, term_to_binary(Ref3)}}, + ?line General ! {apply, {erlang, port_control, [Port, $h, []]}}, + ?line expect({trace_ts, General, in, {?MODULE, general, 0}, ts}), + ?line expect({trace_ts, General, out, {?MODULE, general, 0}, ts}), + ?line General ! {send, Tracer, Msg3}, + ?line expect({trace_ts, General, in, {?MODULE, general, 0}, ts}), + ?line expect({trace_ts, General, send, Msg3, Tracer, ts}), + ?line expect(Ref3), + ?line expect({trace_ts, General, out, {?MODULE, general, 0}, ts}), + ?line expect(), + %% + ok. + +fake_schedule_after_register(doc) -> + "Tests fake out/in scheduling contents."; +fake_schedule_after_register(Config) when is_list(Config) -> + ?line run_fake_sched_test(fun fake_schedule_after_register_test/1, Config). + +fake_schedule_after_register_test(Config) when is_list(Config) -> + ?line start_tracer(Config), + ?line Port = get(tracer_port), + ?line G1 = fun_spawn(fun general/0), + ?line G2 = fun_spawn(fun general/0), + %% + ?line trac(G1, true, [running, timestamp, procs]), + ?line trac(G2, true, [running, timestamp]), + %% + %% Test fake out/in scheduling after certain messages + ?line erlang:yield(), + ?line G2 ! {apply, {erlang, port_control, [Port, $h, []]}}, + ?line G2 ! {apply, {erlang, register, [fake_schedule_after_register, G1]}}, + ?line expect({trace_ts, G2, in, {?MODULE, general, 0}, ts}), + ?line {_,_,_,_,Ts} = + expect({trace_ts, G1, register, fake_schedule_after_register, ts}), + ?line expect({trace_ts, G2, out, 0, Ts}), + ?line expect({trace_ts, G2, in, 0, ts}), + ?line expect({trace_ts, G2, out, {?MODULE, general, 0}, ts}), + ?line expect(), + %% + ok. + +fake_schedule_after_getting_linked(doc) -> + "Tests fake out/in scheduling contents."; +fake_schedule_after_getting_linked(Config) when is_list(Config) -> + ?line run_fake_sched_test(fun fake_schedule_after_getting_linked_test/1, + Config). + +fake_schedule_after_getting_linked_test(Config) when is_list(Config) -> + ?line start_tracer(Config), + ?line Port = get(tracer_port), + ?line G1 = fun_spawn(fun general/0), + ?line G2 = fun_spawn(fun general/0), + %% + ?line trac(G1, true, [running, timestamp, procs]), + ?line trac(G2, true, [running, timestamp]), + %% + %% Test fake out/in scheduling after certain messages + ?line erlang:yield(), + ?line G2 ! {apply, {erlang, port_control, [Port, $h, []]}}, + ?line G2 ! {apply, {erlang, link, [G1]}}, + ?line expect({trace_ts, G2, in, {?MODULE, general, 0}, ts}), + ?line {_,_,_,_,Ts} = + expect({trace_ts, G1, getting_linked, G2, ts}), + ?line expect({trace_ts, G2, out, 0, Ts}), + ?line expect({trace_ts, G2, in, 0, ts}), + ?line expect({trace_ts, G2, out, {?MODULE, general, 0}, ts}), + ?line expect(), + %% + ok. + +fake_schedule_after_getting_unlinked(doc) -> + "Tests fake out/in scheduling contents."; +fake_schedule_after_getting_unlinked(Config) when is_list(Config) -> + ?line run_fake_sched_test(fun fake_schedule_after_getting_unlinked_test/1, + Config). + +fake_schedule_after_getting_unlinked_test(Config) when is_list(Config) -> + ?line start_tracer(Config), + ?line Port = get(tracer_port), + ?line G1 = fun_spawn(fun general/0), + ?line G2 = fun_spawn(fun general/0), + %% + ?line trac(G1, true, [running, procs]), + ?line trac(G2, true, [running, timestamp]), + %% + %% Test fake out/in scheduling after certain messages + ?line erlang:yield(), + ?line G2 ! {apply, {erlang, link, [G1]}}, + ?line G2 ! {apply, {erlang, port_control, [Port, $h, []]}}, + ?line G2 ! {apply, {erlang, unlink, [G1]}}, + ?line expect({trace_ts, G2, in, {?MODULE, general, 0}, ts}), + ?line expect({trace, G1, getting_linked, G2}), + ?line expect({trace, G1, getting_unlinked, G2}), + ?line expect({trace_ts, G2, out, 0, ts}), + ?line expect({trace_ts, G2, in, 0, ts}), + ?line expect({trace_ts, G2, out, {?MODULE, general, 0}, ts}), + ?line expect(), + %% + ok. + +gc(doc) -> "Test sending garbage collection events to a port."; +gc(Config) when is_list(Config) -> + ?line start_tracer(Config), + ?line Garber = fun_spawn(fun garber/0, [{min_heap_size, 5000}]), + ?line trac(Garber, true, [garbage_collection]), + ?line trace_info(Garber, flags), + + ?line trace_info(Garber, flags), + Garber ! hi, + expect({trace,Garber,gc_start,info}), + expect({trace,Garber,gc_end,info}), + + ?line trac(Garber, true, [garbage_collection,timestamp]), + Garber ! hi, + expect({trace_ts,Garber,gc_start,info,ts}), + expect({trace_ts,Garber,gc_end,info,ts}), + + ok. + +default_tracer(doc) -> + "Test a port as default tracer."; +default_tracer(Config) when is_list(Config) -> + ?line Tracer = start_tracer(Config), + ?line TracerMonitor = erlang:monitor(process, Tracer), + ?line Port = get(tracer_port), + %% + ?line N = erlang:trace(all, true, [send, {tracer, Port}]), + ?line {flags, [send]} = erlang:trace_info(self(), flags), + ?line {tracer, Port} = erlang:trace_info(self(), tracer), + ?line {flags, [send]} = erlang:trace_info(new, flags), + ?line {tracer, Port} = erlang:trace_info(new, tracer), + ?line G1 = fun_spawn(fun general/0), + ?line {flags, [send]} = erlang:trace_info(G1, flags), + ?line {tracer, Port} = erlang:trace_info(G1, tracer), + ?line unlink(Tracer), + ?line exit(Port, done), + ?line receive + {'DOWN', TracerMonitor, process, Tracer, TracerExitReason} -> + ?line done = TracerExitReason + end, + ?line {flags, []} = erlang:trace_info(self(), flags), + ?line {tracer, []} = erlang:trace_info(self(), tracer), + ?line {flags, []} = erlang:trace_info(new, flags), + ?line {tracer, []} = erlang:trace_info(new, tracer), + ?line M = erlang:trace(all, false, [all]), + ?line {flags, []} = erlang:trace_info(self(), flags), + ?line {tracer, []} = erlang:trace_info(self(), tracer), + ?line {flags, []} = erlang:trace_info(G1, flags), + ?line {tracer, []} = erlang:trace_info(G1, tracer), + ?line G1 ! {apply,{erlang,exit,[normal]}}, + ?line io:format("~p = ~p.~n", [M, N]), + ?line M = N, + ok. + + +%%% Help functions. + +huge_data() -> + case os:type() of + vxworks -> huge_data(4711); + _ -> huge_data(16384) + end. +huge_data(0) -> []; +huge_data(N) when N rem 2 == 0 -> + P = huge_data(N div 2), + [P|P]; +huge_data(N) -> + P = huge_data(N div 2), + [16#1234566,P|P]. + +expect() -> + receive + Other -> + ok = io:format("Unexpected; got ~p", [Other]), + test_server:fail({unexpected, Other}) + after 200 -> + ok + end. + +expect({trace_ts,E1,E2,info,ts}=Message) -> + receive + {trace_ts,E1,E2,_Info,_Ts}=MessageTs -> + ok = io:format("Expected and got ~p", [MessageTs]), + MessageTs; + Other -> + io:format("Expected ~p; got ~p", [Message,Other]), + test_server:fail({unexpected,Other}) + after 5000 -> + io:format("Expected ~p; got nothing", [Message]), + test_server:fail(no_trace_message) + end; +expect({trace,E1,E2,info}=Message) -> + receive + {trace,E1,E2,_Info}=MessageTs -> + ok = io:format("Expected and got ~p", [MessageTs]), + MessageTs; + Other -> + io:format("Expected ~p; got ~p", [Message,Other]), + test_server:fail({unexpected,Other}) + after 5000 -> + io:format("Expected ~p; got nothing", [Message]), + test_server:fail(no_trace_message) + end; +expect({trace_ts,E1,E2,E3,ts}=Message) -> + receive + {trace_ts,E1,E2,E3,_Ts}=MessageTs -> + ok = io:format("Expected and got ~p", [MessageTs]), + MessageTs; + Other -> + io:format("Expected ~p; got ~p", [Message,Other]), + test_server:fail({unexpected,Other}) + after 5000 -> + io:format("Expected ~p; got nothing", [Message]), + test_server:fail(no_trace_message) + end; +expect({trace_ts,E1,E2,E3,E4,ts}=Message) -> + receive + {trace_ts,E1,E2,E3,E4,_Ts}=MessageTs -> + ok = io:format("Expected and got ~p", [MessageTs]), + MessageTs; + Other -> + io:format("Expected ~p; got ~p", [Message,Other]), + test_server:fail({unexpected,Other}) + after 5000 -> + io:format("Expected ~p; got nothing", [Message]), + test_server:fail(no_trace_message) + end; +expect(Message) -> + receive + Message -> + ok = io:format("Expected and got ~p", [Message]), + Message; + Other -> + io:format("Expected ~p; got ~p", [Message,Other]), + test_server:fail({unexpected,Other}) + after 5000 -> + io:format("Expected ~p; got nothing", [Message]), + test_server:fail(no_trace_message) + end. + +trac(What, On, Flags0) -> + Flags = [{tracer,get(tracer_port)}|Flags0], + get(tracer) ! {apply,self(),{erlang,trace,[What,On,Flags]}}, + Res = receive + {apply_result,Result} -> Result + end, + ok = io:format("erlang:trace(~p, ~p, ~p) -> ~p", + [What,On,Flags,Res]), + Res. + +trace_info(What, Key) -> + get(tracer) ! {apply,self(),{erlang,trace_info,[What,Key]}}, + Res = receive + {apply_result,Result} -> Result + end, + ok = io:format("erlang:trace_info(~p, ~p) -> ~p", + [What,Key,Res]), + Res. + +trace_func(MFA, MatchProg) -> + get(tracer) ! {apply,self(),{erlang,trace_pattern,[MFA,MatchProg]}}, + Res = receive + {apply_result,Result} -> Result + end, + ok = io:format("erlang:trace_pattern(~p, ~p) -> ~p", [MFA,MatchProg,Res]), + Res. + +trace_func(MFA, MatchProg, Flags) -> + get(tracer) ! {apply,self(),{erlang,trace_pattern,[MFA,MatchProg,Flags]}}, + Res = receive + {apply_result,Result} -> Result + end, + ok = io:format("erlang:trace_pattern(~p, ~p) -> ~p", [MFA,MatchProg,Res]), + Res. + +trace_pid(Pid, On, Flags0) -> + Flags = [{tracer,get(tracer_port)}|Flags0], + get(tracer) ! {apply,self(),{erlang,trace,[Pid,On,Flags]}}, + Res = receive + {apply_result,Result} -> Result + end, + ok = io:format("erlang:trace(~p, ~p, ~p) -> ~p", + [Pid,On,Flags,Res]), + Res. + +start_tracer(Config) -> + Path = ?config(data_dir, Config), + ok = load_driver(Path, echo_drv), + Self = self(), + put(tracer, fun_spawn(fun() -> tracer(Self) end)), + receive + {started,Port} -> + put(tracer_port, Port) + end, + get(tracer). + +load_driver(Dir, Driver) -> + case erl_ddll:load_driver(Dir, Driver) of + ok -> ok; + {error, Error} = Res -> + io:format("~s\n", [erl_ddll:format_error(Error)]), + Res + end. + +tracer(RelayTo) -> + Port = open_port({spawn,echo_drv}, [eof,binary]), + RelayTo ! {started,Port}, + tracer_loop(RelayTo, Port). + +tracer_loop(RelayTo, Port) -> + receive + {apply,From,{M,F,A}} -> + From ! {apply_result,apply(M, F, A)}, + tracer_loop(RelayTo, Port); + {Port,{data,Msg}} -> + RelayTo ! binary_to_term(Msg), + tracer_loop(RelayTo, Port); + Other -> + exit({bad_message,Other}) + end. + +fun_spawn(Fun) -> + spawn_link(erlang, apply, [Fun,[]]). + +fun_spawn(Fun, Opts) -> + spawn_opt(erlang, apply, [Fun,[]], [link | Opts]). + +% flush() -> +% receive +% X -> +% [X | flush()] +% after 2000 -> +% [] +% end. + + +%%% Models for various kinds of processes. + +%% Sends messages when ordered to. + +sender() -> + receive + {send_please, To, What} -> + To ! What, + sender() + end. + +%% Just consumes messages from its message queue. + +receiver() -> + receive + _Any -> receiver() + end. + +%% Does a garbage collection when it receives a message. + +garber() -> + receive + _Any -> + lists:seq(1, 100), + erlang:garbage_collect(), + garber() + end. + +%% All-purpose process + +general() -> + receive + {apply, {M, F, Args}} -> + erlang:apply(M, F, Args), + general(); + {send, Dest, Msg} -> + Dest ! Msg, + general(); + {call_f_1, Arg} -> + f(Arg), + general(); + nop -> + general() + end. + +f(Arg) -> + Arg. diff --git a/erts/emulator/test/trace_port_SUITE_data/Makefile.src b/erts/emulator/test/trace_port_SUITE_data/Makefile.src new file mode 100644 index 0000000000..c1bf142ccf --- /dev/null +++ b/erts/emulator/test/trace_port_SUITE_data/Makefile.src @@ -0,0 +1,3 @@ +all: echo_drv@dll@ + +@SHLIB_RULES@ diff --git a/erts/emulator/test/trace_port_SUITE_data/echo_drv.c b/erts/emulator/test/trace_port_SUITE_data/echo_drv.c new file mode 100644 index 0000000000..15c4ca11fe --- /dev/null +++ b/erts/emulator/test/trace_port_SUITE_data/echo_drv.c @@ -0,0 +1,107 @@ +#include <stdio.h> +#include "erl_driver.h" + + + +/* ------------------------------------------------------------------------- +** Data types +**/ + +enum e_heavy { + heavy_off, heavy_set, heavy_reset +}; + +typedef struct _erl_drv_data { + ErlDrvPort erlang_port; + enum e_heavy heavy; +} EchoDrvData; + +static EchoDrvData echo_drv_data, *echo_drv_data_p; + + + +/* ------------------------------------------------------------------------- +** Entry struct +**/ + +static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command); +static void echo_drv_stop(EchoDrvData *data_p); +static void echo_drv_output(EchoDrvData *data_p, char *buf, int len); +static void echo_drv_finish(void); +static int echo_drv_control(EchoDrvData *data_p, unsigned int command, + char *buf, int len, + char **rbuf, int rlen); + +static ErlDrvEntry echo_drv_entry = { + NULL, /* init */ + echo_drv_start, + echo_drv_stop, + echo_drv_output, + NULL, /* ready_input */ + NULL, /* ready_output */ + "echo_drv", + echo_drv_finish, + NULL, /* handle */ + echo_drv_control, + NULL, /* timeout */ + NULL, /* outputv */ + NULL /* ready_async */ +}; + + + +/* ------------------------------------------------------------------------- +** Entry functions +**/ + +DRIVER_INIT(echo_drv) +{ + echo_drv_data_p = NULL; + return &echo_drv_entry; +} + +static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command) +{ + if (echo_drv_data_p != NULL) { + return ERL_DRV_ERROR_GENERAL; + } + echo_drv_data_p = &echo_drv_data; + echo_drv_data_p->erlang_port = port; + echo_drv_data_p->heavy = heavy_off; + return echo_drv_data_p; +} + +static void echo_drv_stop(EchoDrvData *data_p) { + echo_drv_data_p = NULL; +} + +static void echo_drv_output(EchoDrvData *data_p, char *buf, int len) { + driver_output(data_p->erlang_port, buf, len); + switch (data_p->heavy) { + case heavy_off: + break; + case heavy_set: + set_port_control_flags(data_p->erlang_port, PORT_CONTROL_FLAG_HEAVY); + data_p->heavy = heavy_reset; + break; + case heavy_reset: + set_port_control_flags(data_p->erlang_port, 0); + data_p->heavy = heavy_off; + break; + } +} + +static void echo_drv_finish() { + echo_drv_data_p = NULL; +} + +static int echo_drv_control(EchoDrvData *data_p, unsigned int command, + char *buf, int len, + char **rbuf, int rlen) { + switch (command) { + case 'h': + data_p->heavy = heavy_set; + break; + } + return 0; +} diff --git a/erts/emulator/test/tuple_SUITE.erl b/erts/emulator/test/tuple_SUITE.erl new file mode 100644 index 0000000000..c4edb16d68 --- /dev/null +++ b/erts/emulator/test/tuple_SUITE.erl @@ -0,0 +1,283 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(tuple_SUITE). +-export([all/1, t_size/1, t_tuple_size/1, t_element/1, t_setelement/1, + t_list_to_tuple/1, t_tuple_to_list/1, + t_make_tuple_2/1, t_make_tuple_3/1, t_append_element/1, + build_and_match/1, tuple_with_case/1, tuple_in_guard/1]). +-include("test_server.hrl"). + +%% Tests tuples and the BIFs: +%% +%% size(Tuple) +%% element/2 +%% setelement/3 +%% tuple_to_list/1 +%% list_to_tuple/1 +%% make_tuple/2 +%% + +all(suite) -> + [build_and_match, t_size, t_tuple_size, + t_list_to_tuple, t_tuple_to_list, + t_element, t_setelement, t_make_tuple_2, + t_make_tuple_3, t_append_element, + tuple_with_case, tuple_in_guard]. + +build_and_match(Config) when is_list(Config) -> + ?line {} = id({}), + ?line {1} = id({1}), + ?line {1, 2} = id({1, 2}), + ?line {1, 2, 3} = id({1, 2, 3}), + ?line {1, 2, 3, 4} = id({1, 2, 3, 4}), + ?line {1, 2, 3, 4, 5} = id({1, 2, 3, 4, 5}), + ?line {1, 2, 3, 4, 5, 6} = id({1, 2, 3, 4, 5, 6}), + ?line {1, 2, 3, 4, 5, 6} = id({1, 2, 3, 4, 5, 6}), + ?line {1, 2, 3, 4, 5, 6, 7} = id({1, 2, 3, 4, 5, 6, 7}), + ?line {1, 2, 3, 4, 5, 6, 7, 8} = id({1, 2, 3, 4, 5, 6, 7, 8}), + ok. + +%% Tests size(Tuple). + +t_size(Config) when is_list(Config) -> + ?line 0 = size({}), + ?line 1 = size({a}), + ?line 1 = size({{a}}), + ?line 2 = size({{a}, {b}}), + ?line 3 = size({1, 2, 3}), + ok. + +t_tuple_size(Config) when is_list(Config) -> + ?line 0 = tuple_size(id({})), + ?line 1 = tuple_size(id({a})), + ?line 1 = tuple_size(id({{a}})), + ?line 2 = tuple_size(id({{a},{b}})), + ?line 3 = tuple_size(id({1,2,3})), + + %% Error cases. + ?line {'EXIT',{badarg,_}} = (catch tuple_size([])), + ?line {'EXIT',{badarg,_}} = (catch tuple_size(<<1,2,3>>)), + ?line error = ludicrous_tuple_size({a,b,c}), + ?line error = ludicrous_tuple_size([a,b,c]), + ok. + + +ludicrous_tuple_size(T) + when tuple_size(T) =:= 16#7777777777777777777777777777777777 -> ok; +ludicrous_tuple_size(T) -> error. + +%% Tests element/2. + +t_element(Config) when is_list(Config) -> + ?line a = element(1, {a}), + ?line a = element(1, {a, b}), + + ?line List = lists:seq(1, 4096), + ?line Tuple = list_to_tuple(lists:seq(1, 4096)), + ?line get_elements(List, Tuple, 1), + + ?line {'EXIT', {badarg, _}} = (catch element(0, id({a,b}))), + ?line {'EXIT', {badarg, _}} = (catch element(3, id({a,b}))), + ?line {'EXIT', {badarg, _}} = (catch element(1, id({}))), + ?line {'EXIT', {badarg, _}} = (catch element(1, id([a,b]))), + ?line {'EXIT', {badarg, _}} = (catch element(1, id(42))), + ?line {'EXIT', {badarg, _}} = (catch element(id(1.5), id({a,b}))), + + ok. + +get_elements([Element|Rest], Tuple, Pos) -> + ?line Element = element(Pos, Tuple), + ?line get_elements(Rest, Tuple, Pos+1); +get_elements([], _Tuple, _Pos) -> + ok. + +%% Tests set_element/3. + +t_setelement(Config) when is_list(Config) -> + ?line {x} = setelement(1, id({1}), x), + ?line {x,2} = setelement(1, id({1,2}), x), + ?line {1,x} = setelement(2, id({1,2}), x), + + ?line Tuple = list_to_tuple(lists:duplicate(2048, x)), + ?line NewTuple = set_all_elements(Tuple, 1), + ?line NewTuple = list_to_tuple(lists:seq(1+7, 2048+7)), + + ?line {'EXIT', {badarg, _}} = (catch setelement(0, {a, b}, x)), + ?line {'EXIT', {badarg, _}} = (catch setelement(3, {a, b}, x)), + ?line {'EXIT', {badarg, _}} = (catch setelement(1, {}, x)), + ?line {'EXIT', {badarg, _}} = (catch setelement(1, [a, b], x)), + ?line {'EXIT', {badarg, _}} = (catch setelement(1.5, {a, b}, x)), + + %% Nested setelement with literals. + AnotherTuple = id({0,0,a,b,c}), + {93748793749387837476555412,3.0,gurka,b,c} = + setelement(1, setelement(2, setelement(3, AnotherTuple, gurka), + 3.0), 93748793749387837476555412), + + ok. + +set_all_elements(Tuple, Pos) when Pos =< size(Tuple) -> + set_all_elements(setelement(Pos, Tuple, Pos+7), Pos+1); +set_all_elements(Tuple, Pos) when Pos > size(Tuple) -> + Tuple. + +%% Tests list_to_tuple/1. + +t_list_to_tuple(Config) when is_list(Config) -> + ?line {} = list_to_tuple([]), + ?line {a} = list_to_tuple([a]), + ?line {a, b} = list_to_tuple([a, b]), + ?line {a, b, c} = list_to_tuple([a, b, c]), + ?line {a, b, c, d} = list_to_tuple([a, b, c, d]), + ?line {a, b, c, d, e} = list_to_tuple([a, b, c, d, e]), + + ?line Size = 4096, + ?line Tuple = list_to_tuple(lists:seq(1, Size)), + ?line Size = size(Tuple), + + ?line {'EXIT', {badarg, _}} = (catch list_to_tuple(id({a,b}))), + ?line {'EXIT', {badarg, _}} = (catch list_to_tuple(id([a|b]))), + ?line {'EXIT', {badarg, _}} = (catch list_to_tuple(id([a|b]))), + + ok. + +%% Tests tuple_to_list/1. + +t_tuple_to_list(Config) when is_list(Config) -> + ?line [] = tuple_to_list({}), + ?line [a] = tuple_to_list({a}), + ?line [a, b] = tuple_to_list({a, b}), + ?line [a, b, c] = tuple_to_list({a, b, c}), + ?line [a, b, c, d] = tuple_to_list({a, b, c, d}), + ?line [a, b, c, d] = tuple_to_list({a, b, c, d}), + + ?line Size = 4096, + ?line List = lists:seq(1, Size), + ?line Tuple = list_to_tuple(List), + ?line Size = size(Tuple), + ?line List = tuple_to_list(Tuple), + + ?line {'EXIT', {badarg,_}} = (catch tuple_to_list(id(a))), + ?line {'EXIT', {badarg,_}} = (catch tuple_to_list(id(42))), + + ok. + +%% Tests the make_tuple/2 BIF. +t_make_tuple_2(Config) when is_list(Config) -> + ?line t_make_tuple1([]), + ?line t_make_tuple1(42), + ?line t_make_tuple1(a), + ?line t_make_tuple1({}), + ?line t_make_tuple1({a}), + ?line t_make_tuple1(erlang:make_tuple(400, [])), + ok. + +t_make_tuple1(Element) -> + lists:foreach(fun(Size) -> t_make_tuple(Size, Element) end, + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 255, 256, 511, 512, 999, + 1000, 1023, 1024, 4095, 4096]). + +t_make_tuple(Size, Element) -> + Tuple = erlang:make_tuple(Size, Element), + lists:foreach(fun(El) when El =:= Element -> + ok; + (Other) -> + test_server:fail({got, Other, expected, Element}) + end, tuple_to_list(Tuple)). + +%% Tests the erlang:make_tuple/3 BIF. +t_make_tuple_3(Config) when is_list(Config) -> + ?line {} = erlang:make_tuple(0, def, []), + ?line {def} = erlang:make_tuple(1, def, []), + ?line {a} = erlang:make_tuple(1, def, [{1,a}]), + ?line {a,def,c,def,e} = erlang:make_tuple(5, def, [{5,e},{1,a},{3,c}]), + ?line {a,def,c,def,e} = erlang:make_tuple(5, def, + [{1,blurf},{5,e},{3,blurf}, + {1,a},{3,c}]), + + %% Error cases. + ?line {'EXIT',{badarg,_}} = (catch erlang:make_tuple(0, def, [{1,a}])), + ?line {'EXIT',{badarg,_}} = (catch erlang:make_tuple(5, def, [{-1,a}])), + ?line {'EXIT',{badarg,_}} = (catch erlang:make_tuple(5, def, [{0,a}])), + ?line {'EXIT',{badarg,_}} = (catch erlang:make_tuple(5, def, [{6,z}])), + ?line {'EXIT',{badarg,_}} = (catch erlang:make_tuple(a, def, [{6,z}])), + ?line {'EXIT',{badarg,_}} = (catch erlang:make_tuple(5, def, [{1,a}|b])), + ?line {'EXIT',{badarg,_}} = (catch erlang:make_tuple(5, def, [42])), + ?line {'EXIT',{badarg,_}} = (catch erlang:make_tuple(5, def, [[a,b,c]])), + ?line {'EXIT',{badarg,_}} = (catch erlang:make_tuple(5, def, non_list)), + ok. + +%% Tests the append_element/2 BIF. +t_append_element(Config) when is_list(Config) -> + t_append_element({}, 2048, 2048). + +t_append_element(_Tuple, 0, _High) -> ok; +t_append_element(Tuple, N, High) -> + NewTuple = erlang:append_element(Tuple, N), + verify_seq(tuple_to_list(Tuple), High, N), + t_append_element(NewTuple, N-1, High). + +verify_seq([], High, High) -> ok; +verify_seq([High], High, High) -> ok; +verify_seq([High|T], High, Lower) -> + verify_seq(T, High-1, Lower). + +%% Tests that a case nested inside a tuple is ok. +%% (This is known to crash earlier versions of BEAM.) + +tuple_with_case(Config) when is_list(Config) -> + ?line {reply, true} = tuple_with_case(), + ok. + +tuple_with_case() -> + %% The following comments apply to the BEAM compiler. + foo(), % Reset var count. + {reply, % Compiler will choose {x,1} for tuple. + case foo() of % Call will reset var count. + {'EXIT', Reason} -> % Case will return in {x,1} (first free). + {error, Reason}; % but the tuple will be build in {x,1}, + _ -> % so case value is lost and a circular + true % data element is built. + end}. + +foo() -> ignored. + +%% Test to build a tuple in a guard. + +tuple_in_guard(Config) when is_list(Config) -> + ?line Tuple1 = id({a,b}), + ?line Tuple2 = id({a,b,c}), + ?line if + Tuple1 == {element(1, Tuple2),element(2, Tuple2)} -> + ok; + true -> + ?line test_server:fail() + end, + ?line if + Tuple2 == {element(1, Tuple2),element(2, Tuple2), + element(3, Tuple2)} -> + ok; + true -> + ?line test_server:fail() + end, + ok. + +%% Use this function to avoid compile-time evaluation of an expression. +id(I) -> I. + diff --git a/erts/emulator/test/z_SUITE.erl b/erts/emulator/test/z_SUITE.erl new file mode 100644 index 0000000000..67d2b288a2 --- /dev/null +++ b/erts/emulator/test/z_SUITE.erl @@ -0,0 +1,312 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%%------------------------------------------------------------------- +%%% File : z_SUITE.erl +%%% Author : Rickard Green <[email protected]> +%%% Description : Misc tests that should be run last +%%% +%%% Created : 15 Jul 2005 by Rickard Green <[email protected]> +%%%------------------------------------------------------------------- +-module(z_SUITE). +-author('[email protected]'). + +%-define(line_trace, 1). + +-include("test_server.hrl"). + +%-compile(export_all). +-export([all/1, init_per_testcase/2, fin_per_testcase/2]). + +-export([schedulers_alive/1, node_container_refc_check/1, + long_timers/1, pollset_size/1, + check_io_debug/1]). + +-define(DEFAULT_TIMEOUT, ?t:minutes(5)). + +all(doc) -> []; +all(suite) -> + [schedulers_alive, + node_container_refc_check, + long_timers, + pollset_size, + check_io_debug]. + +init_per_testcase(_Case, Config) when is_list(Config) -> + Dog = ?t:timetrap(?DEFAULT_TIMEOUT), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + +%%% +%%% The test cases ------------------------------------------------------------- +%%% + +schedulers_alive(doc) -> ["Tests that all schedulers are actually used"]; +schedulers_alive(suite) -> []; +schedulers_alive(Config) when is_list(Config) -> + ?line Master = self(), + ?line NoSchedulersOnline = erlang:system_flag( + schedulers_online, + erlang:system_info(schedulers)), + ?line NoSchedulers = erlang:system_info(schedulers), + UsedScheds = + try + ?line ?t:format("Number of schedulers configured: ~p~n", [NoSchedulers]), + ?line case erlang:system_info(multi_scheduling) of + blocked -> + ?line ?t:fail(multi_scheduling_blocked); + disabled -> + ?line ok; + enabled -> + ?t:format("Testing blocking process exit~n"), + BF = fun () -> + blocked = erlang:system_flag(multi_scheduling, + block), + Master ! {self(), blocking}, + receive after infinity -> ok end + end, + ?line Blocker = spawn_link(BF), + ?line Mon = erlang:monitor(process, Blocker), + ?line receive {Blocker, blocking} -> ok end, + ?line [Blocker] + = erlang:system_info(multi_scheduling_blockers), + ?line unlink(Blocker), + ?line exit(Blocker, kill), + ?line receive {'DOWN', Mon, _, _, _} -> ok end, + ?line enabled = erlang:system_info(multi_scheduling), + ?line [] = erlang:system_info(multi_scheduling_blockers), + ?line ok + end, + ?t:format("Testing blocked~n"), + ?line erlang:system_flag(multi_scheduling, block), + ?line case erlang:system_info(multi_scheduling) of + enabled -> + ?line ?t:fail(multi_scheduling_enabled); + blocked -> + ?line [Master] = erlang:system_info(multi_scheduling_blockers); + disabled -> ?line ok + end, + ?line Ps = lists:map( + fun (_) -> + spawn_link(fun () -> + run_on_schedulers(none, + [], + Master) + end) + end, + lists:seq(1,NoSchedulers)), + ?line receive after 1000 -> ok end, + ?line {_, 1} = verify_all_schedulers_used({[],0}, 1), + ?line lists:foreach(fun (P) -> + unlink(P), + exit(P, bang) + end, + Ps), + ?line case erlang:system_flag(multi_scheduling, unblock) of + blocked -> ?line ?t:fail(multi_scheduling_blocked); + disabled -> ?line ok; + enabled -> ?line ok + end, + erts_debug:set_internal_state(available_internal_state, true), + %% node_and_dist_references will use emulator interal thread blocking... + erts_debug:get_internal_state(node_and_dist_references), + erts_debug:set_internal_state(available_internal_state, false), + ?t:format("Testing not blocked~n"), + ?line Ps2 = lists:map( + fun (_) -> + spawn_link(fun () -> + run_on_schedulers(none, + [], + Master) + end) + end, + lists:seq(1,NoSchedulers)), + ?line receive after 1000 -> ok end, + ?line {_, NoSIDs} = verify_all_schedulers_used({[],0},NoSchedulers), + ?line lists:foreach(fun (P) -> + unlink(P), + exit(P, bang) + end, + Ps2), + NoSIDs + after + NoSchedulers = erlang:system_flag(schedulers_online, + NoSchedulersOnline), + NoSchedulersOnline = erlang:system_info(schedulers_online) + end, + ?line {comment, "Number of schedulers " ++ integer_to_list(UsedScheds)}. + + +run_on_schedulers(LastSID, SIDs, ReportTo) -> + case erlang:system_info(scheduler_id) of + LastSID -> + erlang:yield(), + run_on_schedulers(LastSID, SIDs, ReportTo); + SID -> + NewSIDs = case lists:member(SID, SIDs) of + true -> + SIDs; + false -> + ReportTo ! {scheduler_used, SID}, + [SID | SIDs] + end, + erlang:yield(), + run_on_schedulers(SID, NewSIDs, ReportTo) + end. + +wait_on_used_scheduler({SIDs, SIDsLen} = State) -> + receive + {scheduler_used, SID} -> + case lists:member(SID, SIDs) of + true -> + wait_on_used_scheduler(State); + false -> + ?t:format("Scheduler ~p used~n", [SID]), + {[SID|SIDs], SIDsLen+1} + end + end. + +verify_all_schedulers_used({UsedSIDs, UsedSIDsLen} = State, NoSchedulers) -> + ?line case NoSchedulers of + UsedSIDsLen -> + ?line State; + NoSchdlrs when NoSchdlrs < UsedSIDsLen -> + ?line ?t:fail({more_schedulers_used_than_exist, + {existing_schedulers, NoSchdlrs}, + {used_schedulers, UsedSIDsLen}, + {used_scheduler_ids, UsedSIDs}}); + _ -> + ?line NewState = wait_on_used_scheduler(State), + ?line verify_all_schedulers_used(NewState, NoSchedulers) + end. + +node_container_refc_check(doc) -> []; +node_container_refc_check(suite) -> []; +node_container_refc_check(Config) when is_list(Config) -> + ?line node_container_SUITE:node_container_refc_check(node()), + ?line ok. + +long_timers(doc) -> + []; +long_timers(suite) -> + []; +long_timers(Config) when is_list(Config) -> + ?line ok = long_timers_test:check_result(). + +pollset_size(doc) -> + []; +pollset_size(suite) -> + []; +pollset_size(Config) when is_list(Config) -> + ?line Name = pollset_size_testcase_initial_state_holder, + ?line Mon = erlang:monitor(process, Name), + ?line (catch Name ! {get_initial_check_io_result, self()}), + ?line InitChkIo = receive + {initial_check_io_result, ICIO} -> + ?line erlang:demonitor(Mon, [flush]), + ?line ICIO; + {'DOWN', Mon, _, _, Reason} -> + ?line ?t:fail({non_existing, Name, Reason}) + end, + ?line FinChkIo = get_check_io_info(), + ?line io:format("Initial: ~p~nFinal: ~p~n", [InitChkIo, FinChkIo]), + ?line InitPollsetSize = lists:keysearch(total_poll_set_size, 1, InitChkIo), + ?line FinPollsetSize = lists:keysearch(total_poll_set_size, 1, FinChkIo), + ?line case InitPollsetSize =:= FinPollsetSize of + true -> + case InitPollsetSize of + {value, {total_poll_set_size, Size}} -> + ?line {comment, + "Pollset size: " ++ integer_to_list(Size)}; + _ -> + ?line {skipped, + "Pollset size information not available"} + end; + false -> + %% Somtimes we have fewer descriptors in the + %% pollset at the end than when we started, but + %% that is ok as long as there are at least 2 + %% descriptors (dist listen socket and + %% epmd socket) in the pollset. + ?line {value, {total_poll_set_size, InitSize}} + = InitPollsetSize, + ?line {value, {total_poll_set_size, FinSize}} + = FinPollsetSize, + ?line true = FinSize < InitSize, + ?line true = 2 =< FinSize, + ?line {comment, + "Start pollset size: " + ++ integer_to_list(InitSize) + ++ " End pollset size: " + ++ integer_to_list(FinSize)} + end. + +check_io_debug(doc) -> + []; +check_io_debug(suite) -> + []; +check_io_debug(Config) when is_list(Config) -> + ?line case lists:keysearch(name, 1, erlang:system_info(check_io)) of + {value, {name, erts_poll}} -> ?line check_io_debug_test(); + _ -> ?line {skipped, "Not implemented in this emulator"} + end. + +check_io_debug_test() -> + ?line erts_debug:set_internal_state(available_internal_state, true), + ?line erlang:display(erlang:system_info(check_io)), + ?line NoOfErrorFds = erts_debug:get_internal_state(check_io_debug), + ?line erts_debug:set_internal_state(available_internal_state, false), + ?line 0 = NoOfErrorFds, + ?line ok. + + + +%% +%% Internal functions... +%% + +display_check_io(ChkIo) -> + catch erlang:display('--- CHECK IO INFO ---'), + catch erlang:display(ChkIo), + catch erts_debug:set_internal_state(available_internal_state, true), + NoOfErrorFds = (catch erts_debug:get_internal_state(check_io_debug)), + catch erlang:display({'NoOfErrorFds', NoOfErrorFds}), + catch erts_debug:set_internal_state(available_internal_state, false), + catch erlang:display('--- CHECK IO INFO ---'), + ok. + +get_check_io_info() -> + ChkIo = erlang:system_info(check_io), + case lists:keysearch(pending_updates, 1, ChkIo) of + {value, {pending_updates, 0}} -> + display_check_io(ChkIo), + ChkIo; + false -> + ChkIo; + _ -> + receive after 10 -> ok end, + get_check_io_info() + end. + + + |