aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/test
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /erts/emulator/test
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'erts/emulator/test')
-rw-r--r--erts/emulator/test/Makefile194
-rw-r--r--erts/emulator/test/a_SUITE.erl99
-rw-r--r--erts/emulator/test/a_SUITE_data/Makefile.src10
-rw-r--r--erts/emulator/test/a_SUITE_data/timer_driver.c77
-rw-r--r--erts/emulator/test/after_SUITE.erl233
-rw-r--r--erts/emulator/test/alloc_SUITE.erl179
-rw-r--r--erts/emulator/test/alloc_SUITE_data/Makefile.src41
-rw-r--r--erts/emulator/test/alloc_SUITE_data/allocator_test.h131
-rw-r--r--erts/emulator/test/alloc_SUITE_data/basic.c61
-rw-r--r--erts/emulator/test/alloc_SUITE_data/bucket_index.c114
-rw-r--r--erts/emulator/test/alloc_SUITE_data/bucket_mask.c147
-rw-r--r--erts/emulator/test/alloc_SUITE_data/coalesce.c318
-rw-r--r--erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.c102
-rw-r--r--erts/emulator/test/alloc_SUITE_data/rbtree.c386
-rw-r--r--erts/emulator/test/alloc_SUITE_data/realloc_copy.c279
-rw-r--r--erts/emulator/test/alloc_SUITE_data/testcase_driver.c260
-rw-r--r--erts/emulator/test/alloc_SUITE_data/testcase_driver.h51
-rw-r--r--erts/emulator/test/alloc_SUITE_data/threads.c447
-rw-r--r--erts/emulator/test/beam_SUITE.erl281
-rw-r--r--erts/emulator/test/beam_literals_SUITE.erl433
-rw-r--r--erts/emulator/test/beam_literals_SUITE_data/literal_case_expression.S70
-rw-r--r--erts/emulator/test/bif_SUITE.erl317
-rw-r--r--erts/emulator/test/big_SUITE.erl396
-rw-r--r--erts/emulator/test/big_SUITE_data/borders.dat1116
-rw-r--r--erts/emulator/test/big_SUITE_data/eq_28.dat3000
-rw-r--r--erts/emulator/test/big_SUITE_data/eq_32.dat3000
-rw-r--r--erts/emulator/test/big_SUITE_data/eq_big.dat13004
-rw-r--r--erts/emulator/test/big_SUITE_data/eq_math.dat78
-rw-r--r--erts/emulator/test/big_SUITE_data/literal_test.erl38
-rw-r--r--erts/emulator/test/big_SUITE_data/negative.dat10
-rw-r--r--erts/emulator/test/binary_SUITE.erl1313
-rw-r--r--erts/emulator/test/binary_SUITE_data/bad_binarybin0 -> 3279 bytes
-rw-r--r--erts/emulator/test/binary_SUITE_data/zzz.terms.11971
-rw-r--r--erts/emulator/test/binary_SUITE_data/zzz.terms.22241
-rw-r--r--erts/emulator/test/binary_SUITE_data/zzz.terms.246191
-rw-r--r--erts/emulator/test/binary_SUITE_data/zzz.terms.256811
-rw-r--r--erts/emulator/test/binary_SUITE_data/zzz.terms.265631
-rw-r--r--erts/emulator/test/binary_SUITE_data/zzz.terms.267441
-rw-r--r--erts/emulator/test/binary_SUITE_data/zzz.terms.274591
-rw-r--r--erts/emulator/test/binary_SUITE_data/zzz.terms.5271
-rw-r--r--erts/emulator/test/binary_SUITE_data/zzz.terms.89291
-rw-r--r--erts/emulator/test/bs_bincomp_SUITE.erl130
-rw-r--r--erts/emulator/test/bs_bit_binaries_SUITE.erl183
-rw-r--r--erts/emulator/test/bs_construct_SUITE.erl790
-rw-r--r--erts/emulator/test/bs_match_bin_SUITE.erl195
-rw-r--r--erts/emulator/test/bs_match_int_SUITE.erl331
-rw-r--r--erts/emulator/test/bs_match_misc_SUITE.erl537
-rw-r--r--erts/emulator/test/bs_match_tail_SUITE.erl87
-rw-r--r--erts/emulator/test/bs_utf_SUITE.erl394
-rw-r--r--erts/emulator/test/busy_port_SUITE.erl628
-rw-r--r--erts/emulator/test/busy_port_SUITE_data/Makefile.src25
-rw-r--r--erts/emulator/test/busy_port_SUITE_data/busy_drv.c97
-rw-r--r--erts/emulator/test/busy_port_SUITE_data/hard_busy_drv.c23
-rw-r--r--erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c94
-rw-r--r--erts/emulator/test/busy_port_SUITE_data/soft_busy_drv.c23
-rw-r--r--erts/emulator/test/call_trace_SUITE.erl1240
-rw-r--r--erts/emulator/test/code_SUITE.erl520
-rw-r--r--erts/emulator/test/code_SUITE_data/another_code_test.erl23
-rw-r--r--erts/emulator/test/code_SUITE_data/cpbugx.erl45
-rw-r--r--erts/emulator/test/code_SUITE_data/literals.erl83
-rw-r--r--erts/emulator/test/code_SUITE_data/many_funs.erl47
-rw-r--r--erts/emulator/test/code_SUITE_data/my_code_test.erl27
-rw-r--r--erts/emulator/test/crypto_SUITE.erl330
-rw-r--r--erts/emulator/test/crypto_reference.erl856
-rw-r--r--erts/emulator/test/ddll_SUITE.erl1120
-rw-r--r--erts/emulator/test/ddll_SUITE_data/Makefile.src3
-rw-r--r--erts/emulator/test/ddll_SUITE_data/dummy_drv.c49
-rw-r--r--erts/emulator/test/ddll_SUITE_data/echo_drv.c52
-rw-r--r--erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c59
-rw-r--r--erts/emulator/test/ddll_SUITE_data/initfail_drv.c46
-rw-r--r--erts/emulator/test/ddll_SUITE_data/lock_drv.c55
-rw-r--r--erts/emulator/test/ddll_SUITE_data/noinit_drv.c58
-rw-r--r--erts/emulator/test/ddll_SUITE_data/wrongname_drv.c50
-rw-r--r--erts/emulator/test/decode_packet_SUITE.erl514
-rw-r--r--erts/emulator/test/dgawd_handler.erl118
-rw-r--r--erts/emulator/test/dist_init_unix_SUITE_data/hosts.dn_sp7
-rw-r--r--erts/emulator/test/dist_init_unix_SUITE_data/hosts.underscore7
-rw-r--r--erts/emulator/test/dist_init_unix_SUITE_data/nsswitch.conf.dn_sp31
-rw-r--r--erts/emulator/test/dist_init_unix_SUITE_data/resolv.conf.dn_sp6
-rw-r--r--erts/emulator/test/distribution_SUITE.erl1842
-rw-r--r--erts/emulator/test/distribution_SUITE_data/Makefile.src4
-rw-r--r--erts/emulator/test/distribution_SUITE_data/run.erl48
-rw-r--r--erts/emulator/test/driver_SUITE.erl1993
-rw-r--r--erts/emulator/test/driver_SUITE_data/Makefile.src33
-rw-r--r--erts/emulator/test/driver_SUITE_data/caller_drv.c134
-rw-r--r--erts/emulator/test/driver_SUITE_data/chkio_drv.c1575
-rw-r--r--erts/emulator/test/driver_SUITE_data/invalid_extended_marker_drv.c32
-rw-r--r--erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c151
-rw-r--r--erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c423
-rw-r--r--erts/emulator/test/driver_SUITE_data/larger_major_vsn_drv.c31
-rw-r--r--erts/emulator/test/driver_SUITE_data/larger_minor_vsn_drv.c31
-rw-r--r--erts/emulator/test/driver_SUITE_data/many_events_drv.c98
-rw-r--r--erts/emulator/test/driver_SUITE_data/missing_callback_drv.c144
-rw-r--r--erts/emulator/test/driver_SUITE_data/monitor_drv.c293
-rw-r--r--erts/emulator/test/driver_SUITE_data/otp_6879_drv.c71
-rw-r--r--erts/emulator/test/driver_SUITE_data/outputv_drv.c63
-rw-r--r--erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c231
-rw-r--r--erts/emulator/test/driver_SUITE_data/queue_drv.c195
-rw-r--r--erts/emulator/test/driver_SUITE_data/smaller_major_vsn_drv.c31
-rw-r--r--erts/emulator/test/driver_SUITE_data/smaller_minor_vsn_drv.c31
-rw-r--r--erts/emulator/test/driver_SUITE_data/sys_info_1_0_drv.c72
-rw-r--r--erts/emulator/test/driver_SUITE_data/sys_info_1_1_drv.c80
-rw-r--r--erts/emulator/test/driver_SUITE_data/sys_info_curr_drv.c77
-rw-r--r--erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c154
-rw-r--r--erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.h29
-rw-r--r--erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c125
-rw-r--r--erts/emulator/test/driver_SUITE_data/timer_drv.c96
-rw-r--r--erts/emulator/test/driver_SUITE_data/vsn_mismatch_drv_impl.c67
-rw-r--r--erts/emulator/test/driver_SUITE_data/zero_extended_marker_garb_drv.c32
-rw-r--r--erts/emulator/test/efile_SUITE.erl76
-rw-r--r--erts/emulator/test/efile_SUITE_data/existing_file1
-rw-r--r--erts/emulator/test/emulator.spec1
-rw-r--r--erts/emulator/test/emulator.spec.ose2
-rw-r--r--erts/emulator/test/emulator.spec.vxworks26
-rw-r--r--erts/emulator/test/emulator.spec.win2
-rw-r--r--erts/emulator/test/erl_drv_thread_SUITE.erl119
-rw-r--r--erts/emulator/test/erl_drv_thread_SUITE_data/Makefile.src33
-rw-r--r--erts/emulator/test/erl_drv_thread_SUITE_data/basic.c291
-rw-r--r--erts/emulator/test/erl_drv_thread_SUITE_data/rwlock.c214
-rw-r--r--erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c260
-rw-r--r--erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.h58
-rw-r--r--erts/emulator/test/erl_drv_thread_SUITE_data/tsd.c173
-rw-r--r--erts/emulator/test/erl_link_SUITE.erl1133
-rw-r--r--erts/emulator/test/erts_debug_SUITE.erl72
-rw-r--r--erts/emulator/test/estone_SUITE.erl1107
-rw-r--r--erts/emulator/test/estone_SUITE_data/Makefile.src15
-rw-r--r--erts/emulator/test/estone_SUITE_data/estone_cat.c40
-rwxr-xr-xerts/emulator/test/estone_SUITE_data/sunspeed.sh10
-rw-r--r--erts/emulator/test/evil_SUITE.erl377
-rw-r--r--erts/emulator/test/exception_SUITE.erl497
-rw-r--r--erts/emulator/test/float_SUITE.erl167
-rw-r--r--erts/emulator/test/float_SUITE_data/Makefile.src8
-rw-r--r--erts/emulator/test/float_SUITE_data/fp_drv.c142
-rw-r--r--erts/emulator/test/float_SUITE_data/has_fpe_bug.erl31
-rw-r--r--erts/emulator/test/fun_SUITE.erl884
-rw-r--r--erts/emulator/test/fun_r11_SUITE.erl76
-rw-r--r--erts/emulator/test/gc_SUITE.erl181
-rw-r--r--erts/emulator/test/guard_SUITE.erl390
-rw-r--r--erts/emulator/test/hash_SUITE.erl717
-rw-r--r--erts/emulator/test/hibernate_SUITE.erl353
l---------erts/emulator/test/ignore_cores.erl1
-rw-r--r--erts/emulator/test/list_bif_SUITE.erl145
-rw-r--r--erts/emulator/test/long_timers_test.erl317
-rw-r--r--erts/emulator/test/match_spec_SUITE.erl942
-rw-r--r--erts/emulator/test/module_info_SUITE.erl105
-rw-r--r--erts/emulator/test/monitor_SUITE.erl943
-rw-r--r--erts/emulator/test/nested_SUITE.erl92
-rw-r--r--erts/emulator/test/nif_SUITE.erl235
-rw-r--r--erts/emulator/test/nif_SUITE_data/Makefile.src14
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_SUITE.1.c2
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_SUITE.c149
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.1.c2
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.2.c2
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.3.c2
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.c103
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.erl64
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.h17
-rw-r--r--erts/emulator/test/node_container_SUITE.erl1288
-rw-r--r--erts/emulator/test/nofrag_SUITE.erl208
-rw-r--r--erts/emulator/test/num_bif_SUITE.erl268
-rw-r--r--erts/emulator/test/obsolete_SUITE.erl123
-rw-r--r--erts/emulator/test/obsolete_SUITE_data/Makefile.src33
-rw-r--r--erts/emulator/test/obsolete_SUITE_data/erl_threads.c302
-rw-r--r--erts/emulator/test/obsolete_SUITE_data/testcase_driver.c262
-rw-r--r--erts/emulator/test/obsolete_SUITE_data/testcase_driver.h57
-rw-r--r--erts/emulator/test/old_mod.erl47
-rw-r--r--erts/emulator/test/old_scheduler_SUITE.erl394
-rw-r--r--erts/emulator/test/op_SUITE.erl368
-rw-r--r--erts/emulator/test/port_SUITE.erl2288
-rw-r--r--erts/emulator/test/port_SUITE_data/Makefile.src26
-rw-r--r--erts/emulator/test/port_SUITE_data/dir/dummy1
-rw-r--r--erts/emulator/test/port_SUITE_data/echo_args.c12
-rw-r--r--erts/emulator/test/port_SUITE_data/echo_drv.c85
-rw-r--r--erts/emulator/test/port_SUITE_data/exit_drv.c68
-rw-r--r--erts/emulator/test/port_SUITE_data/failure_drv.c63
-rw-r--r--erts/emulator/test/port_SUITE_data/port_test.c605
-rw-r--r--erts/emulator/test/port_SUITE_data/port_test.erl36
-rw-r--r--erts/emulator/test/port_SUITE_data/reclaim.h60
-rw-r--r--erts/emulator/test/port_bif_SUITE.erl446
-rw-r--r--erts/emulator/test/port_bif_SUITE_data/Makefile.src14
-rw-r--r--erts/emulator/test/port_bif_SUITE_data/control_drv.c84
-rw-r--r--erts/emulator/test/port_bif_SUITE_data/port_test.c602
-rw-r--r--erts/emulator/test/port_bif_SUITE_data/reclaim.h60
-rw-r--r--erts/emulator/test/process_SUITE.erl2067
-rw-r--r--erts/emulator/test/pseudoknot_SUITE.erl3326
-rw-r--r--erts/emulator/test/random_iolist.erl195
-rw-r--r--erts/emulator/test/ref_SUITE.erl58
-rw-r--r--erts/emulator/test/register_SUITE.erl87
-rw-r--r--erts/emulator/test/save_calls_SUITE.erl256
-rw-r--r--erts/emulator/test/scheduler_SUITE.erl1378
-rw-r--r--erts/emulator/test/send_term_SUITE.erl354
-rw-r--r--erts/emulator/test/send_term_SUITE_data/Makefile.src3
-rw-r--r--erts/emulator/test/send_term_SUITE_data/ext_terms.binbin0 -> 476 bytes
-rw-r--r--erts/emulator/test/send_term_SUITE_data/ext_terms.h110
-rw-r--r--erts/emulator/test/send_term_SUITE_data/send_term_drv.c718
-rw-r--r--erts/emulator/test/sensitive_SUITE.erl461
-rw-r--r--erts/emulator/test/signal_SUITE.erl544
-rw-r--r--erts/emulator/test/statistics_SUITE.erl341
-rw-r--r--erts/emulator/test/suite_release.exclude6
-rw-r--r--erts/emulator/test/system_info_SUITE.erl142
-rw-r--r--erts/emulator/test/system_profile_SUITE.erl474
-rw-r--r--erts/emulator/test/system_profile_SUITE_data/Makefile.src3
-rw-r--r--erts/emulator/test/system_profile_SUITE_data/echo_drv.c66
-rw-r--r--erts/emulator/test/time_SUITE.erl439
-rw-r--r--erts/emulator/test/timer_bif_SUITE.erl558
-rw-r--r--erts/emulator/test/trace_SUITE.erl1496
-rw-r--r--erts/emulator/test/trace_bif_SUITE.erl268
-rw-r--r--erts/emulator/test/trace_call_count_SUITE.erl362
-rw-r--r--erts/emulator/test/trace_local_SUITE.erl1259
-rw-r--r--erts/emulator/test/trace_local_SUITE_data/trace_local_dummy.erl28
-rw-r--r--erts/emulator/test/trace_meta_SUITE.erl758
-rw-r--r--erts/emulator/test/trace_nif_SUITE.erl292
-rw-r--r--erts/emulator/test/trace_nif_SUITE_data/Makefile.src7
-rw-r--r--erts/emulator/test/trace_nif_SUITE_data/trace_nif.c46
-rw-r--r--erts/emulator/test/trace_port_SUITE.erl686
-rw-r--r--erts/emulator/test/trace_port_SUITE_data/Makefile.src3
-rw-r--r--erts/emulator/test/trace_port_SUITE_data/echo_drv.c107
-rw-r--r--erts/emulator/test/tuple_SUITE.erl283
-rw-r--r--erts/emulator/test/z_SUITE.erl312
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
new file mode 100644
index 0000000000..6c008e96ee
--- /dev/null
+++ b/erts/emulator/test/binary_SUITE_data/bad_binary
Binary files differ
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
+ "<" -> "&lt;" ++ otp_3906_htmlize(Cs);
+ ">" -> "&gt;" ++ 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
new file mode 100644
index 0000000000..b239284323
--- /dev/null
+++ b/erts/emulator/test/send_term_SUITE_data/ext_terms.bin
Binary files differ
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.
+
+
+