1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1997-2020. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21-module(binary_SUITE).
22
23%% Tests binaries and the BIFs:
24%%	list_to_binary/1
25%%      iolist_to_binary/1
26%%      list_to_bitstring/1
27%%	binary_to_list/1
28%%	binary_to_list/3
29%%	binary_to_term/1
30%%  	binary_to_term/2
31%%      bitstring_to_list/1
32%%	term_to_binary/1
33%%      erlang:external_size/1
34%%	size(Binary)
35%%      iolist_size/1
36%%	split_binary/2
37%%      hash(Binary, N)
38%%      phash(Binary, N)
39%%      phash2(Binary, N)
40%%
41
42-include_lib("common_test/include/ct.hrl").
43-include_lib("common_test/include/ct_event.hrl").
44
45-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
46	 init_per_group/2,end_per_group/2,
47	 init_per_testcase/2, end_per_testcase/2,
48	 copy_terms/1, conversions/1, deep_lists/1, deep_bitstr_lists/1,
49	 bad_list_to_binary/1, bad_binary_to_list/1,
50	 t_split_binary/1, bad_split/1,
51	 terms/1, terms_float/1, float_middle_endian/1,
52         b2t_used_big/1,
53	 external_size/1, t_iolist_size/1,
54         t_iolist_size_huge_list/1,
55         t_iolist_size_huge_bad_arg_list/1,
56         t_iolist_size_shallow_trapping/1,
57         t_iolist_size_shallow_short_lists/1,
58         t_iolist_size_shallow_tiny_lists/1,
59         t_iolist_size_deep_trapping/1,
60         t_iolist_size_deep_short_lists/1,
61         t_iolist_size_deep_tiny_lists/1,
62	 t_hash/1,
63         sub_bin_copy/1,
64	 bad_size/1,
65	 bad_term_to_binary/1,
66	 bad_binary_to_term_2/1,safe_binary_to_term2/1,
67	 bad_binary_to_term/1, bad_terms/1, more_bad_terms/1,
68	 otp_5484/1,otp_5933/1,
69	 ordering/1,unaligned_order/1,gc_test/1,
70	 bit_sized_binary_sizes/1,
71	 otp_6817/1,deep/1,
72         term2bin_tuple_fallbacks/1,
73         robustness/1,otp_8117/1,
74	 otp_8180/1, trapping/1, large/1,
75	 error_after_yield/1, cmp_old_impl/1,
76         t2b_system_limit/1]).
77
78%% Internal exports.
79-export([sleeper/0,trapping_loop/4]).
80
81suite() -> [{ct_hooks,[ts_install_cth]},
82	    {timetrap,{minutes,4}}].
83
84all() ->
85    [copy_terms, conversions, deep_lists, deep_bitstr_lists,
86     t_split_binary, bad_split,
87     bad_list_to_binary, bad_binary_to_list, terms,
88     terms_float, float_middle_endian, external_size, t_iolist_size,
89     t_iolist_size_huge_list,
90     t_iolist_size_huge_bad_arg_list,
91     {group, iolist_size_benchmarks},
92     b2t_used_big,
93     bad_binary_to_term_2, safe_binary_to_term2,
94     bad_binary_to_term, bad_terms, t_hash, bad_size,
95     sub_bin_copy,
96     bad_term_to_binary, t2b_system_limit, more_bad_terms,
97     otp_5484, otp_5933,
98     ordering, unaligned_order, gc_test,
99     bit_sized_binary_sizes, otp_6817, otp_8117, deep,
100     term2bin_tuple_fallbacks,
101     robustness, otp_8180, trapping, large,
102     error_after_yield, cmp_old_impl].
103
104groups() ->
105    [
106     {
107      iolist_size_benchmarks,
108      [],
109      [t_iolist_size_shallow_trapping,
110       t_iolist_size_shallow_short_lists,
111       t_iolist_size_shallow_tiny_lists,
112       t_iolist_size_deep_trapping,
113       t_iolist_size_deep_short_lists,
114       t_iolist_size_deep_tiny_lists
115      ]
116     }
117    ].
118
119init_per_suite(Config) ->
120    A0 = case application:start(sasl) of
121	     ok -> [sasl];
122	     _ -> []
123	 end,
124    A = case application:start(os_mon) of
125	     ok -> [os_mon|A0];
126	     _ -> A0
127	 end,
128    [{started_apps, A}|Config].
129
130end_per_suite(Config) ->
131    As = proplists:get_value(started_apps, Config),
132    lists:foreach(fun (A) -> application:stop(A) end, As),
133    Config.
134
135
136init_per_group(_GroupName, Config) ->
137    Config.
138
139end_per_group(_GroupName, Config) ->
140    Config.
141
142init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
143    Config.
144
145end_per_testcase(_Func, _Config) ->
146    ok.
147
148-define(heap_binary_size, 64).
149
150copy_terms(Config) when is_list(Config) ->
151    Self = self(),
152    Pid = spawn_link(fun() -> copy_server(Self) end),
153    F = fun(Term) ->
154		Pid ! Term,
155		receive
156		    Term -> ok;
157		    Other ->
158			io:format("Sent: ~P\nGot back:~P", [Term,12,Other,12]),
159			ct:fail(bad_term)
160		end
161	end,
162    test_terms(F),
163    ok.
164
165copy_server(Parent) ->
166    receive
167	Term ->
168	    Parent ! Term,
169	    copy_server(Parent)
170    end.
171
172%% Tests list_to_binary/1, binary_to_list/1 and size/1,
173%% using flat lists.
174
175conversions(Config) when is_list(Config) ->
176    test_bin([]),
177    test_bin([1]),
178    test_bin([1, 2]),
179    test_bin([1, 2, 3]),
180    test_bin(lists:seq(0, ?heap_binary_size)),
181    test_bin(lists:seq(0, ?heap_binary_size+1)),
182    test_bin(lists:seq(0, 255)),
183    test_bin(lists:duplicate(50000, $@)),
184
185    %% Binary in list.
186    List = [1,2,3,4,5],
187    B1 = make_sub_binary(list_to_binary(List)),
188    5 = size(B1),
189    5 = size(make_unaligned_sub_binary(B1)),
190    40 = bit_size(B1),
191    40 = bit_size(make_unaligned_sub_binary(B1)),
192    B2 = list_to_binary([42,B1,19]),
193    B2 = list_to_binary([42,make_unaligned_sub_binary(B1),19]),
194    B2 = iolist_to_binary(B2),
195    B2 = iolist_to_binary(make_unaligned_sub_binary(B2)),
196    7 = size(B2),
197    7 = size(make_sub_binary(B2)),
198    56 = bit_size(B2),
199    56 = bit_size(make_sub_binary(B2)),
200    [42,1,2,3,4,5,19] = binary_to_list(B2),
201    [42,1,2,3,4,5,19] = binary_to_list(make_sub_binary(B2)),
202    [42,1,2,3,4,5,19] = binary_to_list(make_unaligned_sub_binary(B2)),
203    [42,1,2,3,4,5,19] = bitstring_to_list(B2),
204    [42,1,2,3,4,5,19] = bitstring_to_list(make_sub_binary(B2)),
205    [42,1,2,3,4,5,19] = bitstring_to_list(make_unaligned_sub_binary(B2)),
206
207    ok.
208
209test_bin(List) ->
210    Size = length(List),
211    Bin = list_to_binary(List),
212    Bin = iolist_to_binary(List),
213    Bin = list_to_bitstring(List),
214    Size = iolist_size(List),
215    Size = iolist_size(Bin),
216    Size = iolist_size(make_unaligned_sub_binary(Bin)),
217    Size = size(Bin),
218    Size = size(make_sub_binary(Bin)),
219    Size = size(make_unaligned_sub_binary(Bin)),
220    List = binary_to_list(Bin),
221    List = binary_to_list(make_sub_binary(Bin)),
222    List = binary_to_list(make_unaligned_sub_binary(Bin)),
223    List = bitstring_to_list(Bin),
224    List = bitstring_to_list(make_unaligned_sub_binary(Bin)).
225
226%% Tests list_to_binary/1, iolist_to_binary/1, list_to_bitstr/1, binary_to_list/1,3,
227%% bitstr_to_list/1, and size/1, using deep lists.
228
229deep_lists(Config) when is_list(Config) ->
230    test_deep_list(["abc"]),
231    test_deep_list([[12,13,[123,15]]]),
232    test_deep_list([[12,13,[lists:seq(0, 255), []]]]),
233    ok.
234
235test_deep_list(List) ->
236    FlatList = lists:flatten(List),
237    Size = length(FlatList),
238    Bin = list_to_binary(List),
239    Bin = iolist_to_binary(List),
240    Bin = iolist_to_binary(Bin),
241    Bin = list_to_bitstring(List),
242    Size = size(Bin),
243    Size = iolist_size(List),
244    Size = iolist_size(FlatList),
245    Size = iolist_size(Bin),
246    Bitsize = bit_size(Bin),
247    Bitsize = 8*Size,
248    FlatList = binary_to_list(Bin),
249    FlatList = bitstring_to_list(Bin),
250    io:format("testing plain binary..."),
251    t_binary_to_list_3(FlatList, Bin, 1, Size),
252    io:format("testing unaligned sub binary..."),
253    t_binary_to_list_3(FlatList, make_unaligned_sub_binary(Bin), 1, Size).
254
255t_binary_to_list_3(List, Bin, From, To) ->
256    going_up(List, Bin, From, To),
257    going_down(List, Bin, From, To),
258    going_center(List, Bin, From, To).
259
260going_up(List, Bin, From, To) when From =< To ->
261    List = binary_to_list(Bin, From, To),
262    going_up(tl(List), Bin, From+1, To);
263going_up(_List, _Bin, From, To) when From > To ->
264    ok.
265
266going_down(List, Bin, From, To) when To > 0->
267    compare(List, binary_to_list(Bin, From, To), To-From+1),
268    going_down(List, Bin, From, To-1);
269going_down(_List, _Bin, _From, _To) ->
270    ok.
271
272going_center(List, Bin, From, To) when From >= To ->
273    compare(List, binary_to_list(Bin, From, To), To-From+1),
274    going_center(tl(List), Bin, From+1, To-1);
275going_center(_List, _Bin, _From, _To) ->
276    ok.
277
278compare([X|Rest1], [X|Rest2], Left) when Left > 0 ->
279    compare(Rest1, Rest2, Left-1);
280compare([_X|_], [_Y|_], _Left) ->
281    ct:fail("compare fail");
282compare(_List, [], 0) ->
283    ok.
284
285deep_bitstr_lists(Config) when is_list(Config) ->
286    {<<7:3>>,[<<7:3>>]} = test_deep_bitstr([<<7:3>>]),
287    {<<42,5:3>>=Bin,[42,<<5:3>>]=List} = test_deep_bitstr([42,<<5:3>>]),
288    {Bin,List} = test_deep_bitstr([42|<<5:3>>]),
289    {Bin,List} = test_deep_bitstr([<<42,5:3>>]),
290    {Bin,List} = test_deep_bitstr([<<1:3>>,<<10:5>>|<<5:3>>]),
291    {Bin,List} = test_deep_bitstr([<<1:3>>,<<10:5>>,<<5:3>>]),
292    {Bin,List} = test_deep_bitstr([[<<1:3>>,<<10:5>>],[],<<5:3>>]),
293    {Bin,List} = test_deep_bitstr([[[<<1:3>>]|<<10:5>>],[],<<5:3>>]),
294    {Bin,List} = test_deep_bitstr([[<<0:1>>,<<0:1>>,[],<<1:1>>,<<10:5>>],
295					 <<1:1>>,<<0:1>>,<<1:1>>]),
296    ok.
297
298test_deep_bitstr(List) ->
299    %%{'EXIT',{badarg,_}} = list_to_binary(List),
300    Bin = list_to_bitstring(List),
301    {Bin,bitstring_to_list(Bin)}.
302
303bad_list_to_binary(Config) when is_list(Config) ->
304    test_bad_bin(<<1:1>>),
305    test_bad_bin(atom),
306    test_bad_bin(42),
307    test_bad_bin([1|2]),
308    test_bad_bin([256]),
309    test_bad_bin([255, [256]]),
310    test_bad_bin([-1]),
311    test_bad_bin([atom_in_list]),
312    test_bad_bin([[<<8>>]|bad_tail]),
313
314    {'EXIT',{badarg,_}} = (catch list_to_binary(id(<<1,2,3>>))),
315    {'EXIT',{badarg,_}} = (catch list_to_binary(id([<<42:7>>]))),
316    {'EXIT',{badarg,_}} = (catch list_to_bitstring(id(<<1,2,3>>))),
317
318    %% Funs used to be implemented as a type of binary internally.
319    test_bad_bin(fun(X, Y) -> X*Y end),
320    test_bad_bin([1,fun(X) -> X + 1 end,2|fun() -> 0 end]),
321    test_bad_bin([fun(X) -> X + 1 end]),
322
323    %% Test iolists that do not fit in the address space.
324    %% Unfortunately, it would be too slow to test in a 64-bit emulator.
325    case erlang:system_info(wordsize) of
326	4 -> huge_iolists();
327	_ -> ok
328    end.
329
330huge_iolists() ->
331    FourGigs = 1 bsl 32,
332    Sizes = [FourGigs+N || N <- lists:seq(0, 64)] ++
333	[1 bsl N || N <- lists:seq(33, 37)],
334    Base = <<0:(1 bsl 20)/unit:8>>,
335    [begin
336	 L = build_iolist(Sz, Base),
337	 {'EXIT',{system_limit,_}} = (catch list_to_binary([L])),
338	 {'EXIT',{system_limit,_}} = (catch list_to_bitstring([L])),
339	 {'EXIT',{system_limit,_}} = (catch binary:list_to_bin([L])),
340	 {'EXIT',{system_limit,_}} = (catch iolist_to_binary(L))
341	 end || Sz <- Sizes],
342    ok.
343
344test_bad_bin(List) ->
345    {'EXIT',{badarg,_}} = (catch list_to_binary(List)),
346    {'EXIT',{badarg,_}} = (catch iolist_to_binary(List)),
347    {'EXIT',{badarg,_}} = (catch list_to_bitstring(List)),
348    {'EXIT',{badarg,_}} = (catch iolist_size(List)).
349
350%% Tries binary_to_list/1,3 with bad arguments.
351bad_binary_to_list(Config) when is_list(Config) ->
352    bad_bin_to_list(fun(X) -> X * 42 end),
353
354    GoodBin = list_to_binary(lists:seq(1, 10)),
355    bad_bin_to_list(fun(X) -> X * 44 end, 1, 2),
356    bad_bin_to_list(GoodBin, 0, 1),
357    bad_bin_to_list(GoodBin, 2, 1),
358    bad_bin_to_list(GoodBin, 11, 11),
359    {'EXIT',{badarg,_}} = (catch binary_to_list(id(<<42:7>>))),
360    ok.
361
362bad_bin_to_list(BadBin) ->
363    {'EXIT',{badarg,_}} = (catch binary_to_list(BadBin)),
364    {'EXIT',{badarg,_}} = (catch bitstring_to_list(BadBin)).
365
366bad_bin_to_list(Bin, First, Last) ->
367    {'EXIT',{badarg,_}} = (catch binary_to_list(Bin, First, Last)).
368
369
370%% Tries to split a binary at all possible positions.
371
372t_split_binary(Config) when is_list(Config) ->
373    L = lists:seq(0, ?heap_binary_size-5), %Heap binary.
374    B = list_to_binary(L),
375    split(L, B, size(B)),
376
377    %% Sub binary of heap binary.
378    split(L, make_sub_binary(B), size(B)),
379    {X,_Y} = split_binary(B, size(B) div 2),
380    split(binary_to_list(X), X, size(X)),
381
382    %% Unaligned sub binary of heap binary.
383    split(L, make_unaligned_sub_binary(B), size(B)),
384    {X,_Y} = split_binary(B, size(B) div 2),
385    split(binary_to_list(X), X, size(X)),
386
387    %% Reference-counted binary.
388    L2 = lists:seq(0, ?heap_binary_size+1),
389    B2 = list_to_binary(L2),
390    split(L2, B2, size(B2)),
391
392    %% Sub binary of reference-counted binary.
393    split(L2, make_sub_binary(B2), size(B2)),
394    {X2,_Y2} = split_binary(B2, size(B2) div 2),
395    split(binary_to_list(X2), X2, size(X2)),
396
397    %% Unaligned sub binary of reference-counted binary.
398    split(L2, make_unaligned_sub_binary(B2), size(B2)),
399    {X2,_Y2} = split_binary(B2, size(B2) div 2),
400    split(binary_to_list(X2), X2, size(X2)),
401
402    ok.
403
404split(L, B, Pos) when Pos > 0 ->
405    {B1, B2} = split_binary(B, Pos),
406    B1 = list_to_binary(lists:sublist(L, 1, Pos)),
407    B2 = list_to_binary(lists:nthtail(Pos, L)),
408    split(L, B, Pos-1);
409split(_L, _B, 0) ->
410    ok.
411
412%% Tries split_binary/2 with bad arguments.
413bad_split(Config) when is_list(Config) ->
414    GoodBin = list_to_binary([1,2,3]),
415    bad_split(GoodBin, -1),
416    bad_split(GoodBin, 4),
417    bad_split(GoodBin, a),
418
419    %% Funs are a kind of binaries.
420    bad_split(fun(_X) -> 1 end, 1),
421    ok.
422
423bad_split(Bin, Pos) ->
424    {'EXIT',{badarg,_}} = (catch split_binary(Bin, Pos)).
425
426%% Test hash/2 with different type of binaries.
427t_hash(Config) when is_list(Config) ->
428    test_hash([]),
429    test_hash([253]),
430    test_hash(lists:seq(1, ?heap_binary_size)),
431    test_hash(lists:seq(1, ?heap_binary_size+1)),
432    test_hash([X rem 256 || X <- lists:seq(1, 312)]),
433    ok.
434
435test_hash(List) ->
436    Bin = list_to_binary(List),
437    Sbin = make_sub_binary(List),
438    Unaligned = make_unaligned_sub_binary(Sbin),
439    test_hash_1(Bin, Sbin, Unaligned, fun erlang:phash/2),
440    test_hash_1(Bin, Sbin, Unaligned, fun erlang:phash2/2).
441
442test_hash_1(Bin, Sbin, Unaligned, Hash) when is_function(Hash, 2) ->
443    N = 65535,
444    case {Hash(Bin, N),Hash(Sbin, N),Hash(Unaligned, N)} of
445	{H,H,H} -> ok;
446	{H1,H2,H3} ->
447	    ct:fail("Different hash values: ~p, ~p, ~p\n", [H1,H2,H3])
448    end.
449
450%% Try bad arguments to size/1.
451bad_size(Config) when is_list(Config) ->
452    {'EXIT',{badarg,_}} = (catch size(fun(X) -> X + 33 end)),
453    ok.
454
455bad_term_to_binary(Config) when is_list(Config) ->
456    T = id({a,b,c}),
457    {'EXIT',{badarg,_}} = (catch term_to_binary(T, not_a_list)),
458    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [blurf])),
459    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,-1}])),
460    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,10}])),
461    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed,cucumber}])),
462    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{compressed}])),
463    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{version,1}|bad_tail])),
464    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{minor_version,-1}])),
465    {'EXIT',{badarg,_}} = (catch term_to_binary(T, [{minor_version,x}])),
466
467    ok.
468
469t2b_system_limit(Config) when is_list(Config) ->
470    case erlang:system_info(wordsize) of
471        8 ->
472            case proplists:get_value(system_total_memory,
473                                     memsup:get_system_memory_data()) of
474                Memory when is_integer(Memory),
475                            Memory > 6*1024*1024*1024 ->
476                    test_t2b_system_limit(),
477                    garbage_collect(),
478                    ok;
479                _ ->
480                    {skipped, "Not enough memory on this machine"}
481            end;
482        4 ->
483            {skipped, "Only interesting on 64-bit builds"}
484    end.
485
486test_t2b_system_limit() ->
487    io:format("Creating HugeBin~n", []),
488    Bits = ((1 bsl 32)+1)*8,
489    HugeBin = <<0:Bits>>,
490
491    io:format("Testing term_to_binary(HugeBin)~n", []),
492    {'EXIT',{system_limit,[{erlang,term_to_binary,
493                            [HugeBin],
494                            _} |_]}} = (catch term_to_binary(HugeBin)),
495
496    io:format("Testing term_to_binary(HugeBin, [compressed])~n", []),
497    {'EXIT',{system_limit,[{erlang,term_to_binary,
498                            [HugeBin, [compressed]],
499                            _} |_]}} = (catch term_to_binary(HugeBin, [compressed])),
500
501    %% Check that it works also after we have trapped...
502    io:format("Creating HugeListBin~n", []),
503    HugeListBin = [lists:duplicate(2000000,2000000), HugeBin],
504
505    io:format("Testing term_to_binary(HugeListBin)~n", []),
506    {'EXIT',{system_limit,[{erlang,term_to_binary,
507                            [HugeListBin],
508                            _} |_]}} = (catch term_to_binary(HugeListBin)),
509
510    io:format("Testing term_to_binary(HugeListBin, [compressed])~n", []),
511    {'EXIT',{system_limit,[{erlang,term_to_binary,
512                            [HugeListBin, [compressed]],
513                            _} |_]}} = (catch term_to_binary(HugeListBin, [compressed])),
514
515    ok.
516
517%% Tests binary_to_term/1 and term_to_binary/1.
518
519terms(Config) when is_list(Config) ->
520    TestFun = fun(Term) ->
521                      S = io_lib:format("~p", [Term]),
522                      io:put_chars(S),
523		      Bin = term_to_binary(Term),
524		      case erlang:external_size(Bin) of
525			  Sz when is_integer(Sz), size(Bin) =< Sz ->
526			      ok
527		      end,
528                      Bin1 = term_to_binary(Term, [{minor_version, 1}]),
529                      case erlang:external_size(Bin1, [{minor_version, 1}]) of
530                          Sz1 when is_integer(Sz1), size(Bin1) =< Sz1 ->
531                              ok
532                      end,
533		      Term = binary_to_term_stress(Bin),
534		      Term = binary_to_term_stress(Bin, [safe]),
535                      Bin_sz = byte_size(Bin),
536		      {Term,Bin_sz} = binary_to_term_stress(Bin, [used]),
537
538                      BinE = <<Bin/binary, 1, 2, 3>>,
539		      {Term,Bin_sz} = binary_to_term_stress(BinE, [used]),
540
541		      BinU = make_unaligned_sub_binary(Bin),
542		      Term = binary_to_term_stress(BinU),
543		      Term = binary_to_term_stress(BinU, []),
544		      Term = binary_to_term_stress(BinU, [safe]),
545		      {Term,Bin_sz} = binary_to_term_stress(BinU, [used]),
546
547                      BinUE = make_unaligned_sub_binary(BinE),
548		      {Term,Bin_sz} = binary_to_term_stress(BinUE, [used]),
549
550		      BinC = erlang:term_to_binary(Term, [compressed]),
551                      BinC_sz = byte_size(BinC),
552		      true = BinC_sz =< size(Bin),
553		      Term = binary_to_term_stress(BinC),
554		      {Term, BinC_sz} = binary_to_term_stress(BinC, [used]),
555
556		      Bin = term_to_binary(Term, [{compressed,0}]),
557		      terms_compression_levels(Term, size(Bin), 1),
558
559		      BinUC = make_unaligned_sub_binary(BinC),
560		      Term = binary_to_term_stress(BinUC),
561                      {Term,BinC_sz} = binary_to_term_stress(BinUC, [used]),
562
563                      BinCE = <<BinC/binary, 1, 2, 3>>,
564		      {Term,BinC_sz} = binary_to_term_stress(BinCE, [used]),
565
566		      BinUCE = make_unaligned_sub_binary(BinCE),
567		      Term = binary_to_term_stress(BinUCE),
568                      {Term,BinC_sz} = binary_to_term_stress(BinUCE, [used])
569	      end,
570    test_terms(TestFun),
571    ok.
572
573%% Test binary_to_term(_, [used]) returning a big Used integer.
574b2t_used_big(_Config) ->
575    case erlang:system_info(wordsize) of
576        8 ->
577            {skipped, "This is not a 32-bit machine"};
578        4 ->
579            %% Use a long utf8 atom for large external format but compact on heap.
580            BigAtom = binary_to_atom(<< <<16#F0908D88:32>> || _ <- lists:seq(1,255) >>,
581                                     utf8),
582            Atoms = (1 bsl 17) + (1 bsl 9),
583            BigAtomList = lists:duplicate(Atoms, BigAtom),
584            BigBin = term_to_binary(BigAtomList),
585            {BigAtomList, Used} = binary_to_term(BigBin, [used]),
586            2 = erts_debug:size(Used),
587            Used = byte_size(BigBin),
588            Used = 1 + 1 + 4 + Atoms*(1+2+4*255) + 1,
589            ok
590    end.
591
592terms_compression_levels(Term, UncompressedSz, Level) when Level < 10 ->
593    BinC = erlang:term_to_binary(Term, [{compressed,Level}]),
594    Term = binary_to_term_stress(BinC),
595    Sz = byte_size(BinC),
596    true = Sz =< UncompressedSz,
597    terms_compression_levels(Term, UncompressedSz, Level+1);
598terms_compression_levels(_, _, _) -> ok.
599
600terms_float(Config) when is_list(Config) ->
601    test_floats(fun(Term) ->
602			      Bin0 = term_to_binary(Term, [{minor_version,0}]),
603			      Term = binary_to_term_stress(Bin0),
604			      Bin1 = term_to_binary(Term),
605			      Bin1 = term_to_binary(Term, [{minor_version,1}]),
606			      Term = binary_to_term_stress(Bin1),
607			      true = size(Bin1) < size(Bin0),
608                  Size0 = erlang:external_size(Term, [{minor_version, 0}]),
609                  Size1 = erlang:external_size(Term),
610                  Size11 = erlang:external_size(Term, [{minor_version, 1}]),
611                  true = (Size1 =:= Size11),
612                  true = Size1 < Size0
613		      end).
614
615float_middle_endian(Config) when is_list(Config) ->
616    %% Testing for roundtrip is not enough.
617    <<131,70,63,240,0,0,0,0,0,0>> = term_to_binary(1.0, [{minor_version,1}]),
618    1.0 = binary_to_term_stress(<<131,70,63,240,0,0,0,0,0,0>>).
619
620external_size(Config) when is_list(Config) ->
621    %% Build a term whose external size only fits in a big num (on 32-bit CPU).
622    external_size_1(16#11111111111111117777777777777777888889999, 0, 16#FFFFFFF),
623
624    %% Test that the same binary aligned and unaligned has the same external size.
625    Bin = iolist_to_binary([1,2,3,96]),
626    Unaligned = make_unaligned_sub_binary(Bin),
627    case {erlang:external_size(Bin),erlang:external_size(Unaligned)} of
628	{X,X} -> ok;
629	{Sz1,Sz2} ->
630	    ct:fail("  Aligned size: ~p\n"
631                    "Unaligned size: ~p\n", [Sz1,Sz2])
632    end,
633    true = (erlang:external_size(Bin) =:= erlang:external_size(Bin, [{minor_version, 1}])),
634    true = (erlang:external_size(Unaligned) =:= erlang:external_size(Unaligned, [{minor_version, 1}])).
635
636external_size_1(Term, Size0, Limit) when Size0 < Limit ->
637    case erlang:external_size(Term) of
638	Size when is_integer(Size), Size0 < Size ->
639	    io:format("~p", [Size]),
640	    external_size_1([Term|Term], Size, Limit)
641    end;
642external_size_1(_, _, _) -> ok.
643
644t_iolist_size(Config) when is_list(Config) ->
645    _ = rand:uniform(),				%Seed generator
646    io:format("Seed: ~p", [rand:export_seed()]),
647
648    Base = <<0:(1 bsl 20)/unit:8>>,
649    Powers = [1 bsl N || N <- lists:seq(2, 37)],
650    Sizes0 = [[N - rand:uniform(N div 2),
651	       lists:seq(N-2, N+2),
652	       N+N div 2,
653	       N + rand:uniform(N div 2)] ||
654		 N <- Powers],
655
656    %% Test sizes around 1^32 more thoroughly.
657    FourGigs = 1 bsl 32,
658    Sizes1 = [FourGigs+N || N <- lists:seq(-8, 40)] ++ Sizes0,
659    Sizes2 = lists:flatten(Sizes1),
660    Sizes = lists:usort(Sizes2),
661    io:format("~p sizes:", [length(Sizes)]),
662    io:format("~p\n", [Sizes]),
663    _ = [Sz = iolist_size(build_iolist(Sz, Base)) || Sz <- Sizes],
664    ok.
665
666build_iolist(N, Base) when N < 16 ->
667    case rand:uniform(3) of
668	1 ->
669	    <<Bin:N/binary,_/binary>> = Base,
670	    Bin;
671	_ ->
672	    lists:seq(1, N)
673    end;
674build_iolist(N, Base) when N =< byte_size(Base) ->
675    case rand:uniform(3) of
676	1 ->
677	    <<Bin:N/binary,_/binary>> = Base,
678	    Bin;
679	2 ->
680	    <<Bin:N/binary,_/binary>> = Base,
681	    [Bin];
682	3 ->
683	    case N rem 2 of
684		0 ->
685		    L = build_iolist(N div 2, Base),
686		    [L,L];
687		1 ->
688		    L = build_iolist(N div 2, Base),
689		    [L,L,45]
690	    end
691    end;
692build_iolist(N0, Base) ->
693    Small = rand:uniform(15),
694    Seq = lists:seq(1, Small),
695    N = N0 - Small,
696    case N rem 2 of
697	0 ->
698	    L = build_iolist(N div 2, Base),
699	    [L,L|Seq];
700	1 ->
701	    L = build_iolist(N div 2, Base),
702	    [47,L,L|Seq]
703    end.
704
705approx_4GB_bin() ->
706    Bin = lists:duplicate(4194304, 255),
707    BinRet = erlang:iolist_to_binary(lists:duplicate(1124, Bin)),
708    BinRet.
709
710duplicate_iolist(IOList, 0) ->
711    IOList;
712duplicate_iolist(IOList, NrOfTimes) ->
713    duplicate_iolist([IOList, IOList], NrOfTimes - 1).
714
715t_iolist_size_huge_list(Config)  when is_list(Config) ->
716    run_when_enough_resources(
717      fun() ->
718              {TimeToCreateIOList, IOList} = timer:tc(fun()->duplicate_iolist(approx_4GB_bin(), 32) end),
719              {IOListSizeTime, CalculatedSize} = timer:tc(fun()->erlang:iolist_size(IOList) end),
720              20248183924657750016 = CalculatedSize,
721              {comment, io_lib:format("Time to create iolist: ~f s. Time to calculate size: ~f s.",
722                                      [TimeToCreateIOList / 1000000, IOListSizeTime / 1000000])}
723      end).
724
725t_iolist_size_huge_bad_arg_list(Config)  when is_list(Config) ->
726    run_when_enough_resources(
727      fun() ->
728              P = self(),
729              spawn_link(fun()-> IOListTmp = duplicate_iolist(approx_4GB_bin(), 32),
730                                 IOList = [IOListTmp, [badarg]],
731                                 {'EXIT',{badarg,_}} = (catch erlang:iolist_size(IOList)),
732                                 P ! ok
733                         end),
734              receive ok -> ok end
735         end).
736
737%% iolist_size tests for shallow lists
738
739t_iolist_size_shallow_trapping(Config) when is_list(Config) ->
740    Lengths = [2000, 20000, 200000, 200000, 2000000, 20000000],
741    run_iolist_size_test_and_benchmark(Lengths, fun make_shallow_iolist/2).
742
743t_iolist_size_shallow_short_lists(Config) when is_list(Config) ->
744    Lengths = lists:duplicate(15000, 300),
745    run_iolist_size_test_and_benchmark(Lengths, fun make_shallow_iolist/2).
746
747t_iolist_size_shallow_tiny_lists(Config) when is_list(Config) ->
748    Lengths = lists:duplicate(250000, 18),
749    run_iolist_size_test_and_benchmark(Lengths, fun make_shallow_iolist/2).
750
751make_shallow_iolist(SizeDiv2, LastItem) ->
752    lists:map(
753      fun(I) ->
754              case I of
755                  SizeDiv2 -> [1, LastItem];
756                  _ -> [1, 1]
757              end
758      end,
759      lists:seq(1, SizeDiv2)).
760
761%% iolist_size tests for deep lists
762
763t_iolist_size_deep_trapping(Config) when is_list(Config) ->
764    Lengths = [2000, 20000, 200000, 200000, 2000000, 10000000],
765    run_iolist_size_test_and_benchmark(Lengths, fun make_deep_iolist/2).
766
767t_iolist_size_deep_short_lists(Config) when is_list(Config) ->
768    Lengths = lists:duplicate(10000, 300),
769    run_iolist_size_test_and_benchmark(Lengths, fun make_deep_iolist/2).
770
771t_iolist_size_deep_tiny_lists(Config) when is_list(Config) ->
772    Lengths = lists:duplicate(150000, 18),
773    run_iolist_size_test_and_benchmark(Lengths, fun make_deep_iolist/2).
774
775make_deep_iolist(1, LastItem) ->
776    [1, LastItem];
777make_deep_iolist(Depth, LastItem) ->
778    [[1, 1], make_deep_iolist(Depth - 1, LastItem)].
779
780% Helper functions for iolist_size tests
781
782run_iolist_size_test_and_benchmark(Lengths, ListGenerator) ->
783    run_when_enough_resources(
784      fun() ->
785              GoodListsWithSizes =
786                  lists:map(fun(Length) -> {Length*2, ListGenerator(Length, 1)} end, Lengths),
787              BadListsWithSizes =
788                  lists:map(fun(Length) -> {Length*2, ListGenerator(Length, bad)} end, Lengths),
789              erlang:garbage_collect(),
790              report_throughput(
791                fun() ->
792                        lists:foreach(
793                          fun(_)->
794                                  lists:foreach(
795                                    fun({Size, List}) -> Size = iolist_size(List) end,
796                                    GoodListsWithSizes),
797                                  lists:foreach(
798                                    fun({_, List}) -> {'EXIT',_} = (catch (iolist_size(List))) end,
799                                    BadListsWithSizes)
800                          end,
801                          lists:seq(1,3))
802                end,
803                lists:sum(Lengths)*4)
804      end).
805
806report_throughput(Fun, NrOfItems) ->
807    Parent = self(),
808    spawn(fun() -> Parent ! timer:tc(Fun) end),
809    {Time, _} = receive D -> D end,
810    ItemsPerMicrosecond = NrOfItems / Time,
811    ct_event:notify(#event{ name = benchmark_data, data = [{value, ItemsPerMicrosecond}]}),
812    {comment, io_lib:format("Items per microsecond: ~p, Nr of items: ~p, Benchmark time: ~p seconds)",
813                            [ItemsPerMicrosecond, NrOfItems, Time/1000000])}.
814
815total_memory() ->
816    %% Total memory in GB.
817    try
818	MemoryData = memsup:get_system_memory_data(),
819	case lists:keysearch(total_memory, 1, MemoryData) of
820	    {value, {total_memory, TM}} ->
821		TM div (1024*1024*1024);
822	    false ->
823		{value, {system_total_memory, STM}} =
824		    lists:keysearch(system_total_memory, 1, MemoryData),
825		STM div (1024*1024*1024)
826	end
827    catch
828	_ : _ ->
829	    undefined
830    end.
831
832run_when_enough_resources(Fun) ->
833    case {total_memory(), erlang:system_info(wordsize)} of
834        {Mem, 8} when is_integer(Mem) andalso Mem >= 15 ->
835            Fun();
836        {Mem, WordSize} ->
837            {skipped,
838             io_lib:format("Not enough resources (System Memory >= ~p, Word Size = ~p)",
839                           [Mem, WordSize])}
840    end.
841
842
843%% OTP-4053
844bad_binary_to_term_2(Config) when is_list(Config) ->
845    {ok, N} = test_server:start_node(plopp, slave, []),
846    R = rpc:call(N, erlang, binary_to_term, [<<131,111,255,255,255,0>>]),
847    case R of
848	      {badrpc, {'EXIT', _}} ->
849		  ok;
850	      _Other ->
851		  ct:fail({rpcresult, R})
852	  end,
853    test_server:stop_node(N),
854    ok.
855
856%% Try bad input to binary_to_term/1.
857bad_binary_to_term(Config) when is_list(Config) ->
858    bad_bin_to_term(an_atom),
859    bad_bin_to_term({an,tuple}),
860    bad_bin_to_term({a,list}),
861    bad_bin_to_term(fun() -> self() end),
862    bad_bin_to_term(fun(X) -> 42*X end),
863    bad_bin_to_term(fun(X, Y) -> {X,Y} end),
864    bad_bin_to_term(fun(X, Y, Z) -> {X,Y,Z} end),
865    bad_bin_to_term(bit_sized_binary(term_to_binary({you,should,'not',see,this,term}))),
866
867    %% Bad float.
868    bad_bin_to_term(<<131,70,-1:64>>),
869
870    %% Truncated UTF8 character (ERL-474)
871    bad_bin_to_term(<<131,119,1,194,163>>),
872    ok.
873
874bad_bin_to_term(BadBin) ->
875    {'EXIT',{badarg,_}} = (catch binary_to_term_stress(BadBin)).
876
877bad_bin_to_term(BadBin,Opts) ->
878    {'EXIT',{badarg,_}} = (catch binary_to_term_stress(BadBin,Opts)).
879
880%% Test safety options for binary_to_term/2
881safe_binary_to_term2(Config) when is_list(Config) ->
882    bad_bin_to_term(<<131,100,0,14,"undefined_atom">>, [safe]),
883    bad_bin_to_term(<<131,100,0,14,"other_bad_atom">>, [safe]),
884    BadHostAtom = <<100,0,14,"badguy@badhost">>,
885    Empty = <<0,0,0,0>>,
886    BadRef = <<131,114,0,3,BadHostAtom/binary,0,<<0,0,0,255>>/binary,
887	      Empty/binary,Empty/binary>>,
888    bad_bin_to_term(BadRef, [safe]), % good ref, with a bad atom
889    fullsweep_after = binary_to_term_stress(<<131,100,0,15,"fullsweep_after">>, [safe]), % should be a good atom
890    BadExtFun = <<131,113,100,0,4,98,108,117,101,100,0,4,109,111,111,110,97,3>>,
891    bad_bin_to_term(BadExtFun, [safe]),
892    ok.
893
894%% Tests bad input to binary_to_term/1.
895
896bad_terms(Config) when is_list(Config) ->
897    test_terms(fun corrupter/1),
898    {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,3:32,0,11,22,33>>)),
899    {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,3:32,9,11,22,33>>)),
900    {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,0:32,1,11,22,33>>)),
901    {'EXIT',{badarg,_}} = (catch binary_to_term(<<131,$M,-1:32,1,11,22,33>>)),
902    ok.
903
904
905corrupter(Term) when is_function(Term);
906		     is_function(hd(Term));
907		     is_function(element(2,element(2,element(2,Term)))) ->
908    %% Check if lists is native compiled. If it is, we do not try to
909    %% corrupt funs as this can create some very strange behaviour.
910    %% To show the error print `Byte` in the foreach fun in corrupter/2.
911    case erlang:system_info(hipe_architecture) of
912	undefined ->
913	    corrupter0(Term);
914	Architecture ->
915	    {lists, ListsBinary, _ListsFilename} = code:get_object_code(lists),
916	    ChunkName = hipe_unified_loader:chunk_name(Architecture),
917	    NativeChunk = beam_lib:chunks(ListsBinary, [ChunkName]),
918	    case NativeChunk of
919		{ok,{_,[{_,Bin}]}} when is_binary(Bin) ->
920		    S = io_lib:format("Skipping corruption of: ~P", [Term,12]),
921		    io:put_chars(S);
922		{error, beam_lib, _} ->
923		    corrupter0(Term)
924	    end
925    end;
926corrupter(Term) ->
927    corrupter0(Term).
928
929corrupter0(Term) ->
930    try
931	      S = io_lib:format("About to corrupt: ~P", [Term,12]),
932	      io:put_chars(S)
933	  catch
934	      error:badarg ->
935		  io:format("About to corrupt: <<bit-level-binary:~p",
936			    [bit_size(Term)])
937	  end,
938    Bin = term_to_binary(Term),
939    corrupter(Bin, size(Bin)-1),
940    CompressedBin = term_to_binary(Term, [compressed]),
941    corrupter(CompressedBin, size(CompressedBin)-1).
942
943corrupter(Bin, Pos) when Pos >= 0 ->
944    {ShorterBin, Rest} = split_binary(Bin, Pos),
945    catch binary_to_term_stress(ShorterBin), %% emulator shouldn't crash
946    MovedBin = list_to_binary([ShorterBin]),
947    catch binary_to_term_stress(MovedBin), %% emulator shouldn't crash
948
949    %% Bit faults, shouldn't crash
950    <<Byte,Tail/binary>> = Rest,
951    Fun = fun(M) -> FaultyByte = Byte bxor M,
952		    catch binary_to_term_stress(<<ShorterBin/binary,
953					  FaultyByte, Tail/binary>>) end,
954    lists:foreach(Fun,[1,2,4,8,16,32,64,128,255]),
955    corrupter(Bin, Pos-1);
956corrupter(_Bin, _) ->
957    ok.
958
959more_bad_terms(Config) when is_list(Config) ->
960    Data = proplists:get_value(data_dir, Config),
961    BadFile = filename:join(Data, "bad_binary"),
962    ok = io:format("File: ~s\n", [BadFile]),
963    case file:read_file(BadFile) of
964	      {ok,Bin} ->
965		  {'EXIT',{badarg,_}} = (catch binary_to_term_stress(Bin)),
966		  ok;
967	      Other ->
968		  ct:fail(Other)
969	  end.
970
971otp_5484(Config) when is_list(Config) ->
972    {'EXIT',_} =
973	(catch
974	     binary_to_term_stress(
975	       <<131,
976		104,2,				%Tuple, 2 elements
977		103,				%Pid
978		100,0,20,"wslin1427198@wslin14",
979		%% Obviously bad values follow.
980		255,255,255,255,
981		255,255,255,255,
982		255,
983		106>>)),
984
985    {'EXIT',_} =
986	(catch
987	     binary_to_term_stress(
988	       <<131,
989		104,2,				%Tuple, 2 elements
990		103,				%Pid
991		106,				%[] instead of atom.
992		0,0,0,17,
993		0,0,0,135,
994		2,
995		106>>)),
996
997    {'EXIT',_} =
998	(catch
999	     binary_to_term_stress(
1000	       %% A old-type fun in a list containing a bad creator pid.
1001	       <<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>>)),
1002
1003    {'EXIT',_} =
1004	(catch
1005	     binary_to_term_stress(
1006	       %% A new-type fun in a list containing a bad creator pid.
1007	       %%
1008	       <<131,
1009		108,0,0,0,1,			%List, 1 element
1010		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,
1011		103,				%Pid.
1012		106,				%[] instead of an atom.
1013		0,0,0,27,0,0,0,0,0,106>>)),
1014
1015    {'EXIT',_} =
1016	(catch
1017	     binary_to_term_stress(
1018	       %% A new-type fun in a list containing a bad module.
1019	       <<131,
1020		108,0,0,0,1,			%List, 1 element
1021		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,
1022		%%100,0,1,116,
1023		107,0,1,64,			%String instead of atom (same length).
1024		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>>)),
1025
1026    {'EXIT',_} =
1027	(catch
1028	     binary_to_term_stress(
1029	       %% A new-type fun in a list containing a bad index.
1030	       <<131,
1031		108,0,0,0,1,			%List, 1 element
1032		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,
1033		100,0,1,116,
1034		%%97,0,				%Integer: 0.
1035		104,0,				%Tuple {} instead of integer.
1036		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>>)),
1037
1038    {'EXIT',_} =
1039	(catch
1040	     binary_to_term_stress(
1041	       %% A new-type fun in a list containing a bad unique value.
1042	       <<131,
1043		108,0,0,0,1,			%List, 1 element
1044		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,
1045		100,0,1,116,
1046		97,0,				%Integer: 0.
1047		%%98,6,64,82,230,		%Integer.
1048		100,0,2,64,65,			%Atom instead of integer.
1049		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>>)),
1050
1051    %% An absurdly large atom.
1052    {'EXIT',_} =
1053	(catch binary_to_term_stress(iolist_to_binary([<<131,100,65000:16>>|
1054						lists:duplicate(65000, 42)]))),
1055
1056    %% Longer than 255 characters.
1057    {'EXIT',_} =
1058	(catch binary_to_term_stress(iolist_to_binary([<<131,100,256:16>>|
1059						lists:duplicate(256, 42)]))),
1060
1061    %% OTP-7218. Thanks to Matthew Dempsky. Also make sure that we
1062    %% cover the other error cases for external funs (EXPORT_EXT).
1063    {'EXIT',_} =
1064	(catch binary_to_term_stress(
1065		 <<131,
1066		  113,				%EXPORT_EXP
1067		  97,13,			%Integer: 13
1068		  97,13,			%Integer: 13
1069		  97,13>>)),			%Integer: 13
1070    {'EXIT',_} =
1071	(catch binary_to_term_stress(
1072		 <<131,
1073		  113,				%EXPORT_EXP
1074		  100,0,1,64,			%Atom: '@'
1075		  97,13,			%Integer: 13
1076		  97,13>>)),			%Integer: 13
1077    {'EXIT',_} =
1078	(catch binary_to_term_stress(
1079		 <<131,
1080		  113,				%EXPORT_EXP
1081		  100,0,1,64,			%Atom: '@'
1082		  100,0,1,64,			%Atom: '@'
1083		  106>>)),			%NIL
1084    {'EXIT',_} =
1085	(catch binary_to_term_stress(
1086		 <<131,
1087		  113,				%EXPORT_EXP
1088		  100,0,1,64,			%Atom: '@'
1089		  100,0,1,64,			%Atom: '@'
1090		  98,255,255,255,255>>)),	%Integer: -1
1091    {'EXIT',_} =
1092	(catch binary_to_term_stress(
1093		 <<131,
1094		  113,				%EXPORT_EXP
1095		  100,0,1,64,			%Atom: '@'
1096		  100,0,1,64,			%Atom: '@'
1097		  113,97,13,97,13,97,13>>)),	%fun 13:13/13
1098
1099    %% Bad funs.
1100    {'EXIT',_} = (catch binary_to_term_stress(fake_fun(0, lists:seq(0, 256)))),
1101    ok.
1102
1103fake_fun(Arity, Env0) ->
1104    Uniq = erlang:md5([]),
1105    Index = 0,
1106    NumFree = length(Env0),
1107    Mod = list_to_binary(?MODULE_STRING),
1108    OldIndex = 0,
1109    OldUniq = 16#123456,
1110    <<131,Pid/binary>> = term_to_binary(self()),
1111    Env1 = [term_to_binary(Term) || Term <- Env0],
1112    Env = << <<Bin/binary>> || <<131,Bin/binary>> <- Env1 >>,
1113    B = <<Arity,Uniq/binary,Index:32,NumFree:32,
1114	 $d,(byte_size(Mod)):16,Mod/binary,	%Module.
1115	 $a,OldIndex:8,
1116	 $b,OldUniq:32,
1117	 Pid/binary,Env/binary>>,
1118    <<131,$p,(byte_size(B)+4):32,B/binary>>.
1119
1120
1121%% More bad terms submitted by Matthias Lang.
1122otp_5933(Config) when is_list(Config) ->
1123    try_bad_lengths(<<131,$m>>),		%binary
1124    try_bad_lengths(<<131,$n>>),		%bignum
1125    try_bad_lengths(<<131,$o>>),		%huge bignum
1126    ok.
1127
1128try_bad_lengths(B) ->
1129    try_bad_lengths(B, 16#FFFFFFFF).
1130
1131try_bad_lengths(B, L) when L > 16#FFFFFFF0 ->
1132    Bin = <<B/binary,L:32>>,
1133    io:format("~p\n", [Bin]),
1134    {'EXIT',_} = (catch binary_to_term_stress(Bin)),
1135    try_bad_lengths(B, L-1);
1136try_bad_lengths(_, _) -> ok.
1137
1138
1139otp_6817(Config) when is_list(Config) ->
1140    process_flag(min_heap_size, 20000),		%Use the heap, not heap fragments.
1141
1142    %% Floats are only validated when the heap fragment has been allocated.
1143    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>>,
1144    otp_6817_try_bin(BadFloat),
1145
1146    %% {Binary,BadFloat}: When the error in float is discovered, a refc-binary
1147    %% has been allocated and the list of refc-binaries goes through the
1148    %% limbo area between the heap top and stack.
1149    BinAndFloat =
1150	<<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,
1151	 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,
1152	 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,
1153	 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,
1154	 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,
1155	 116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,
1156	 135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,
1157	 154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,
1158	 173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
1159	 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,
1160	 211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
1161	 230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,
1162	 249,250,251,252,253,254,255,99,51,46,49,52,$B,$l,$u,$r,$f,48,48,48,48,48,48,
1163	 48,48,49,50,52,51,52,101,43,48,48,0,0,0,0,0>>,
1164    otp_6817_try_bin(BinAndFloat),
1165
1166    %% {Fun,BadFloat}
1167    FunAndFloat =
1168	<<131,104,2,112,0,0,0,66,0,238,239,135,138,137,216,89,57,22,111,52,126,16,84,
1169	 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,
1170	 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,
1171	 $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>>,
1172    otp_6817_try_bin(FunAndFloat),
1173
1174    %% [ExternalPid|BadFloat]
1175    ExtPidAndFloat =
1176	<<131,108,0,0,0,1,103,100,0,13,107,97,108,108,101,64,115,116,114,105,100,101,
1177	 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,
1178	 48,48,48,48,48,101,43,48,48,0,0,0,0,0>>,
1179    otp_6817_try_bin(ExtPidAndFloat),
1180    ok.
1181
1182otp_6817_try_bin(Bin) ->
1183    erlang:garbage_collect(),
1184
1185    %% If the bug is present, the heap pointer will moved when the invalid term
1186    %% is found and we will have a linked list passing through the limbo area
1187    %% between the heap top and the stack pointer.
1188    catch binary_to_term_stress(Bin),
1189
1190    %% If the bug is present, we will overwrite the pointers in the limbo area.
1191    Filler = erlang:make_tuple(1024, 16#3FA),
1192    id(Filler),
1193
1194    %% Will crash if the bug is present.
1195    erlang:garbage_collect().
1196
1197%% Some bugs in binary_to_term when 32-bit integers are negative.
1198otp_8117(Config) when is_list(Config) ->
1199    [otp_8117_do(Op,-(1 bsl N)) || Op <- ['fun',named_fun,list,tuple],
1200				   N <- lists:seq(0,31)],
1201    ok.
1202
1203otp_8117_do('fun',Neg) ->
1204    % Fun with negative num_free
1205    FunBin = term_to_binary(fun() -> ok end),
1206    <<B1:27/binary,_NumFree:32,Rest/binary>> = FunBin,
1207    bad_bin_to_term(<<B1/binary,Neg:32,Rest/binary>>);
1208otp_8117_do(named_fun,Neg) ->
1209    % Named fun with negative num_free
1210    FunBin = term_to_binary(fun F() -> F end),
1211    <<B1:27/binary,_NumFree:32,Rest/binary>> = FunBin,
1212    bad_bin_to_term(<<B1/binary,Neg:32,Rest/binary>>);
1213otp_8117_do(list,Neg) ->
1214    %% List with negative length
1215    bad_bin_to_term(<<131,104,2,108,Neg:32,97,11,104,1,97,12,97,13,106,97,14>>);
1216otp_8117_do(tuple,Neg) ->
1217    %% Tuple with negative arity
1218    bad_bin_to_term(<<131,104,2,105,Neg:32,97,11,97,12,97,13,97,14>>).
1219
1220
1221%% Tests ordering of binaries.
1222ordering(Config) when is_list(Config) ->
1223    B1 = list_to_binary([7,8,9]),
1224    B2 = make_sub_binary([1,2,3,4]),
1225    B3 = list_to_binary([1,2,3,5]),
1226    Unaligned = make_unaligned_sub_binary(B2),
1227
1228    %% From R8 binaries are compared as strings.
1229
1230    false = B1 == B2,
1231    false = B1 =:= B2,
1232    true = B1 /= B2,
1233    true = B1 =/= B2,
1234
1235    true = B1 > B2,
1236    true = B2 < B3,
1237    true = B2 =< B1,
1238    true = B2 =< B3,
1239
1240    true = B2 =:= Unaligned,
1241    true = B2 == Unaligned,
1242    true = Unaligned < B3,
1243    true = Unaligned =< B3,
1244
1245    %% Binaries are greater than all other terms.
1246
1247    true = B1 > 0,
1248    true = B1 > 39827491247298471289473333333333333333333333333333,
1249    true = B1 > -3489274937438742190467869234328742398347,
1250    true = B1 > 3.14,
1251    true = B1 > [],
1252    true = B1 > [a],
1253    true = B1 > {a},
1254    true = B1 > self(),
1255    true = B1 > make_ref(),
1256    true = B1 > xxx,
1257    true = B1 > fun() -> 1 end,
1258    true = B1 > fun erlang:send/2,
1259
1260    Path = proplists:get_value(priv_dir, Config),
1261    AFile = filename:join(Path, "vanilla_file"),
1262    Port = open_port(AFile, [out]),
1263    true = B1 > Port,
1264
1265    true = B1 >= 0,
1266    true = B1 >= 39827491247298471289473333333333333333333333333333,
1267    true = B1 >= -3489274937438742190467869234328742398347,
1268    true = B1 >= 3.14,
1269    true = B1 >= [],
1270    true = B1 >= [a],
1271    true = B1 >= {a},
1272    true = B1 >= self(),
1273    true = B1 >= make_ref(),
1274    true = B1 >= xxx,
1275    true = B1 >= fun() -> 1 end,
1276    true = B1 >= fun erlang:send/2,
1277    true = B1 >= Port,
1278
1279    ok.
1280
1281%% Test that comparison between binaries with different alignment work.
1282unaligned_order(Config) when is_list(Config) ->
1283    L = lists:seq(0, 7),
1284    [test_unaligned_order(I, J) || I <- L, J <- L],
1285    ok.
1286
1287test_unaligned_order(I, J) ->
1288    Align = {I,J},
1289    io:format("~p ~p", [I,J]),
1290    true = test_unaligned_order_1('=:=', <<1,2,3,16#AA,16#7C,4,16#5F,5,16#5A>>,
1291					<<1,2,3,16#AA,16#7C,4,16#5F,5,16#5A>>,
1292					Align),
1293    false = test_unaligned_order_1('=/=', <<1,2,3>>, <<1,2,3>>, Align),
1294    true = test_unaligned_order_1('==', <<4,5,6>>, <<4,5,6>>, Align),
1295    false = test_unaligned_order_1('/=', <<1,2,3>>, <<1,2,3>>, Align),
1296
1297    true = test_unaligned_order_1('<', <<1,2>>, <<1,2,3>>, Align),
1298    true = test_unaligned_order_1('=<', <<1,2>>, <<1,2,3>>, Align),
1299    true = test_unaligned_order_1('=<', <<1,2,7,8>>, <<1,2,7,8>>, Align),
1300    ok.
1301
1302test_unaligned_order_1(Op, A, B, {Aa,Ba}) ->
1303    erlang:Op(unaligned_sub_bin(A, Aa), unaligned_sub_bin(B, Ba)).
1304
1305test_terms(Test_Func) ->
1306    Test_Func(atom),
1307    Test_Func(''),
1308    Test_Func('a'),
1309    Test_Func('ab'),
1310    Test_Func('abc'),
1311    Test_Func('abcd'),
1312    Test_Func('abcde'),
1313    Test_Func('abcdef'),
1314    Test_Func('abcdefg'),
1315    Test_Func('abcdefgh'),
1316
1317    Test_Func(fun() -> ok end),
1318    X = id([a,{b,c},c]),
1319    Y = id({x,y,z}),
1320    Z = id(1 bsl 8*257),
1321    Test_Func(fun() -> X end),
1322    Test_Func(fun() -> {X,Y} end),
1323    Test_Func([fun() -> {X,Y,Z} end,
1324		     fun() -> {Z,X,Y} end,
1325		     fun() -> {Y,Z,X} end]),
1326
1327    Test_Func({trace_ts,{even_bigger,{some_data,fun() -> ok end}},{1,2,3}}),
1328    Test_Func({trace_ts,{even_bigger,{some_data,<<1,2,3,4,5,6,7,8,9,10>>}},
1329		     {1,2,3}}),
1330
1331    Test_Func(1),
1332    Test_Func(42),
1333    Test_Func(-23),
1334    Test_Func(256),
1335    Test_Func(25555),
1336    Test_Func(-3333),
1337
1338    Test_Func(1.0),
1339
1340    Test_Func(183749783987483978498378478393874),
1341    Test_Func(-37894183749783987483978498378478393874),
1342    Very_Big = very_big_num(),
1343    Test_Func(Very_Big),
1344    Test_Func(-Very_Big+1),
1345
1346    Test_Func([]),
1347    Test_Func("abcdef"),
1348    Test_Func([a, b, 1, 2]),
1349    Test_Func([a|b]),
1350
1351    Test_Func({}),
1352    Test_Func({1}),
1353    Test_Func({a, b}),
1354    Test_Func({a, b, c}),
1355    Test_Func(list_to_tuple(lists:seq(0, 255))),
1356    Test_Func(list_to_tuple(lists:seq(0, 256))),
1357
1358    Test_Func(make_ref()),
1359    Test_Func([make_ref(), make_ref()]),
1360
1361    Test_Func(make_port()),
1362
1363    Test_Func(make_pid()),
1364
1365    Test_Func(Bin0 = list_to_binary(lists:seq(0, 14))),
1366    Test_Func(Bin1 = list_to_binary(lists:seq(0, ?heap_binary_size))),
1367    Test_Func(Bin2 = list_to_binary(lists:seq(0, ?heap_binary_size+1))),
1368    Test_Func(Bin3 = list_to_binary(lists:seq(0, 255))),
1369
1370    Test_Func(make_unaligned_sub_binary(Bin0)),
1371    Test_Func(make_unaligned_sub_binary(Bin1)),
1372    Test_Func(make_unaligned_sub_binary(Bin2)),
1373    Test_Func(make_unaligned_sub_binary(Bin3)),
1374
1375    Test_Func(make_sub_binary(lists:seq(42, 43))),
1376    Test_Func(make_sub_binary([42,43,44])),
1377    Test_Func(make_sub_binary([42,43,44,45])),
1378    Test_Func(make_sub_binary([42,43,44,45,46])),
1379    Test_Func(make_sub_binary([42,43,44,45,46,47])),
1380    Test_Func(make_sub_binary([42,43,44,45,46,47,48])),
1381    Test_Func(make_sub_binary(lists:seq(42, 49))),
1382    Test_Func(make_sub_binary(lists:seq(0, 14))),
1383    Test_Func(make_sub_binary(lists:seq(0, ?heap_binary_size))),
1384    Test_Func(make_sub_binary(lists:seq(0, ?heap_binary_size+1))),
1385    Test_Func(make_sub_binary(lists:seq(0, 255))),
1386
1387    Test_Func(make_unaligned_sub_binary(lists:seq(42, 43))),
1388    Test_Func(make_unaligned_sub_binary([42,43,44])),
1389    Test_Func(make_unaligned_sub_binary([42,43,44,45])),
1390    Test_Func(make_unaligned_sub_binary([42,43,44,45,46])),
1391    Test_Func(make_unaligned_sub_binary([42,43,44,45,46,47])),
1392    Test_Func(make_unaligned_sub_binary([42,43,44,45,46,47,48])),
1393    Test_Func(make_unaligned_sub_binary(lists:seq(42, 49))),
1394    Test_Func(make_unaligned_sub_binary(lists:seq(0, 14))),
1395    Test_Func(make_unaligned_sub_binary(lists:seq(0, ?heap_binary_size))),
1396    Test_Func(make_unaligned_sub_binary(lists:seq(0, ?heap_binary_size+1))),
1397    Test_Func(make_unaligned_sub_binary(lists:seq(0, 255))),
1398
1399    %% Bit level binaries.
1400    Test_Func(<<1:1>>),
1401    Test_Func(<<2:2>>),
1402    Test_Func(<<42:10>>),
1403    Test_Func(list_to_bitstring([<<5:6>>|lists:seq(0, 255)])),
1404
1405    Test_Func(F = fun(A) -> 42*A end),
1406    Test_Func(lists:duplicate(32, F)),
1407
1408    Test_Func(FF = fun binary_SUITE:all/0),
1409    Test_Func(lists:duplicate(32, FF)),
1410
1411    %% Maps.
1412    SmallMap = #{a => 1, b => 2, c => 3},
1413    LargeMap1 = maps:from_list([{list_to_atom(integer_to_list(36#cafe+N*N*N, 36)),N} ||
1414                                   N <- lists:seq(1, 33)]),
1415    LargeMap2 = maps:from_list([{list_to_atom(integer_to_list(36#dead+N, 36)),N} ||
1416                                   N <- lists:seq(1, 50)]),
1417    MapWithMap = LargeMap1#{SmallMap => a, LargeMap1 => LargeMap2, LargeMap2 => LargeMap1,
1418                            [LargeMap1,LargeMap2] => LargeMap1,
1419                            <<"abc">> => SmallMap, <<"qrs">> => LargeMap1,
1420                            <<"xyz">> => LargeMap2 },
1421    Test_Func(#{}),
1422    Test_Func(SmallMap),
1423    Test_Func(LargeMap1),
1424    Test_Func(LargeMap2),
1425    Test_Func(MapWithMap),
1426
1427    ok.
1428
1429test_floats(Test_Func) ->
1430    Test_Func(5.5),
1431    Test_Func(-15.32),
1432    Test_Func(1.2435e25),
1433    Test_Func(1.2333e-20),
1434    Test_Func(199.0e+15),
1435    ok.
1436
1437very_big_num() ->
1438    very_big_num(33, 1).
1439
1440very_big_num(Left, Result) when Left > 0 ->
1441    very_big_num(Left-1, Result*256);
1442very_big_num(0, Result) ->
1443    Result.
1444
1445make_port() ->
1446    hd(erlang:ports()).
1447
1448make_pid() ->
1449    spawn_link(?MODULE, sleeper, []).
1450
1451sleeper() ->
1452    receive after infinity -> ok end.
1453
1454
1455%% Test that binaries are garbage collected properly.
1456gc_test(Config) when is_list(Config) ->
1457    %% Note: This test is only relevant for REFC binaries.
1458    %% Therefore, we take care that all binaries are REFC binaries.
1459    true = 192 > ?heap_binary_size,
1460    B = list_to_binary(lists:seq(1, 192)),
1461    Self = self(),
1462    F1 = fun() ->
1463		 gc(),
1464		 {binary,[]} = process_info(self(), binary),
1465		 Self ! {self(),done}
1466	 end,
1467    F = fun() ->
1468		receive go -> ok end,
1469		{binary,[{_,192,1}]} = process_info(self(), binary),
1470		gc(),
1471		{B1,B2} = my_split_binary(B, 68),
1472		gc(),
1473		gc(),
1474		{binary,L1} = process_info(self(), binary),
1475		[Binfo1,Binfo2,Binfo3] = L1,
1476		{_,192,3} = Binfo1 = Binfo2 = Binfo3,
1477		192 = size(B),
1478		68 = size(B1),
1479		124 = size(B2),
1480		F1()
1481	end,
1482    gc(),
1483    gc(),
1484    192 = size(B),
1485    gc_test1(spawn_opt(erlang, apply, [F,[]], [link,{fullsweep_after,0}])).
1486
1487gc_test1(Pid) ->
1488    gc(),
1489    Pid ! go,
1490    receive
1491	{Pid,done} -> ok
1492    after 10000 ->
1493	    ct:fail("timeout")
1494    end.
1495
1496%% Like split binary, but returns REFC binaries. Only useful for gc_test/1.
1497
1498my_split_binary(B, Pos) ->
1499    Self = self(),
1500    Ref = make_ref(),
1501    spawn(fun() -> Self ! {Ref,split_binary(B, Pos)} end),
1502    receive
1503	{Ref,Result} -> Result
1504    end.
1505
1506gc() ->
1507    erlang:garbage_collect(),
1508    gc1().
1509gc1() -> ok.
1510
1511bit_sized_binary_sizes(Config) when is_list(Config) ->
1512    [bsbs_1(A) || A <- lists:seq(1, 8)],
1513    ok.
1514
1515bsbs_1(A) ->
1516    BinSize = 32+A,
1517    io:format("A: ~p BinSize: ~p", [A,BinSize]),
1518    Bin = binary_to_term_stress(<<131,$M,5:32,A,0,0,0,0,0>>),
1519    BinSize = bit_size(Bin).
1520
1521%% lists:foldl(_,_,lists:seq(_,_)) with less heap consumption
1522lists_foldl_seq(Fun, Acc0, N, To) when N =< To ->
1523    Acc1 = Fun(N, Acc0),
1524    lists_foldl_seq(Fun, Acc1, N+1, To);
1525
1526lists_foldl_seq(_, Acc, _, _) ->
1527    Acc.
1528
1529deep(Config) when is_list(Config) ->
1530    deep_roundtrip(lists_foldl_seq(fun(E, A) ->
1531					   [E,A]
1532				   end, [], 1, 1000000)),
1533    erlang:garbage_collect(),
1534    deep_roundtrip(lists_foldl_seq(fun(E, A) ->
1535					   {E,A}
1536				   end, [], 1, 1000000)),
1537    erlang:garbage_collect(),
1538    deep_roundtrip(lists_foldl_seq(fun(E, A) ->
1539					   fun() -> {E,A} end
1540				   end, [], 1, 1000000)),
1541    erlang:garbage_collect(),
1542    ok.
1543
1544deep_roundtrip(T) ->
1545    B = term_to_binary(T),
1546    T = binary_to_term(B).
1547
1548term2bin_tuple_fallbacks(Config) when is_list(Config) ->
1549    erts_debug:set_internal_state(available_internal_state, true),
1550
1551    term2bin_tf(fun ?MODULE:all/1),
1552    term2bin_tf(<<1:1>>),
1553    term2bin_tf(<<90,80:7>>),
1554
1555    erts_debug:set_internal_state(available_internal_state, false),
1556    ok.
1557
1558term2bin_tf(Term) ->
1559    Tuple = case Term of
1560                Fun when is_function(Fun) ->
1561                    {type, external} = erlang:fun_info(Fun, type),
1562                    {module,M} = erlang:fun_info(Fun, module),
1563                    {name,F} = erlang:fun_info(Fun, name),
1564                    {M,F};
1565                BS when bit_size(BS) rem 8 =/= 0 ->
1566                    Bits = bit_size(BS) rem 8,
1567                    {<<BS/bitstring, 0:(8-Bits)>>, Bits}
1568            end,
1569    Tuple = binary_to_term_stress(erts_debug:get_internal_state({term_to_binary_tuple_fallbacks,Term})).
1570
1571%% Test non-standard encodings never generated by term_to_binary/1
1572%% but recognized by binary_to_term/1.
1573
1574robustness(Config) when is_list(Config) ->
1575    [] = binary_to_term_stress(<<131,107,0,0>>),	%Empty string.
1576    [] = binary_to_term_stress(<<131,108,0,0,0,0,106>>),	%Zero-length list.
1577
1578    %% {[],a} where [] is a zero-length list.
1579    {[],a} = binary_to_term_stress(<<131,104,2,108,0,0,0,0,106,100,0,1,97>>),
1580
1581    %% {42,a} where 42 is a zero-length list with 42 in the tail.
1582    {42,a} = binary_to_term_stress(<<131,104,2,108,0,0,0,0,97,42,100,0,1,97>>),
1583
1584    %% {{x,y},a} where {x,y} is a zero-length list with {x,y} in the tail.
1585    {{x,y},a} = binary_to_term_stress(<<131,104,2,108,0,0,0,0,
1586				      104,2,100,0,1,120,100,0,1,
1587				      121,100,0,1,97>>),
1588
1589    %% Bignums fitting in 32 bits.
1590    16#7FFFFFFF = binary_to_term_stress(<<131,98,127,255,255,255>>),
1591    -1 = binary_to_term_stress(<<131,98,255,255,255,255>>),
1592
1593    ok.
1594
1595%% OTP-8180: Test several terms that have been known to crash the emulator.
1596%% (Thanks to Scott Lystig Fritchie.)
1597otp_8180(Config) when is_list(Config) ->
1598    Data = proplists:get_value(data_dir, Config),
1599    Wc = filename:join(Data, "zzz.*"),
1600    Files = filelib:wildcard(Wc),
1601    [run_otp_8180(F) || F <- Files],
1602    ok.
1603
1604run_otp_8180(Name) ->
1605    io:format("~s", [Name]),
1606    {ok,Bins} = file:consult(Name),
1607    [begin
1608	 io:format("~p\n", [Bin]),
1609	 {'EXIT',{badarg,_}} = (catch binary_to_term_stress(Bin))
1610     end || Bin <- Bins],
1611    ok.
1612
1613%% Test that exit and GC during trapping term_to_binary and binary_to_term
1614%% does not crash.
1615trapping(Config) when is_list(Config)->
1616    do_trapping(5, term_to_binary,
1617		fun() -> [lists:duplicate(2000000,2000000)] end),
1618    do_trapping(5, binary_to_term,
1619		fun() -> [term_to_binary(lists:duplicate(2000000,2000000))] end),
1620    do_trapping(5, binary_to_list,
1621		fun() -> [list_to_binary(lists:duplicate(2000000,$x))] end),
1622    do_trapping(5, list_to_binary,
1623		fun() -> [lists:duplicate(2000000,$x)] end),
1624    do_trapping(5, bitstring_to_list,
1625		fun() -> [list_to_bitstring([lists:duplicate(2000000,$x),<<7:4>>])] end),
1626    do_trapping(5, list_to_bitstring,
1627		fun() -> [[lists:duplicate(2000000,$x),<<7:4>>]] end)
1628    .
1629
1630do_trapping(0, _, _) ->
1631    ok;
1632do_trapping(N, Bif, ArgFun) ->
1633    io:format("N=~p: Do ~p ~s gc.\n", [N, Bif, case N rem 2 of 0 -> "with"; 1 -> "without" end]),
1634    Pid = spawn(?MODULE,trapping_loop,[Bif, ArgFun, 1000, self()]),
1635    receive ok -> ok end,
1636    Ref = make_ref(),
1637    case N rem 2 of
1638	0 ->
1639            erlang:garbage_collect(Pid, [{async,Ref}]),
1640            receive after 1 -> ok end;
1641	1 -> void
1642    end,
1643    exit(Pid, kill),
1644    case N rem 2 of
1645	0 ->
1646            receive {garbage_collect, Ref, _} -> ok end;
1647	1 ->
1648            void
1649    end,
1650    receive after 1 -> ok end,
1651    do_trapping(N-1, Bif, ArgFun).
1652
1653trapping_loop(Bif, ArgFun, N, Pid) ->
1654    Args = ArgFun(),
1655    Pid ! ok,
1656    trapping_loop2(Bif,Args,N).
1657trapping_loop2(_,_,0) ->
1658    ok;
1659trapping_loop2(Bif,Args,N) ->
1660    apply(erlang,Bif,Args),
1661    trapping_loop2(Bif, Args, N-1).
1662
1663large(Config) when is_list(Config) ->
1664    List = lists:flatten(lists:map(fun (_) ->
1665					   [0,1,2,3,4,5,6,7,8]
1666				   end,
1667				   lists:seq(1, 131072))),
1668    Bin = list_to_binary(List),
1669    List = binary_to_list(Bin),
1670    PartList = lists:reverse(tl(tl(lists:reverse(tl(tl(List)))))),
1671    PartList = binary_to_list(Bin, 3, length(List)-2),
1672    ListBS = List ++ [<<7:4>>],
1673    ListBS = bitstring_to_list(list_to_bitstring(ListBS)),
1674    BitStr1 = list_to_bitstring(lists:duplicate(1024*1024, [<<1,5:3>>])),
1675    BitStr1 = list_to_bitstring(bitstring_to_list(BitStr1)),
1676    BitStr2 = list_to_bitstring([lists:duplicate(512*1024, [<<1,5:3>>]),
1677				Bin]),
1678    BitStr2 = list_to_bitstring(bitstring_to_list(BitStr2)),
1679    ok.
1680
1681error_after_yield(Config) when is_list(Config) ->
1682    L2BTrap = {erts_internal, list_to_binary_continue, 1},
1683    error_after_yield(badarg, erlang, list_to_binary, 1, fun () -> [[mk_list(1000000), oops]] end, L2BTrap),
1684    error_after_yield(badarg, erlang, iolist_to_binary, 1, fun () -> [[list2iolist(mk_list(1000000)), oops]] end, L2BTrap),
1685    error_after_yield(badarg, erlang, list_to_bitstring, 1, fun () -> [[list2bitstrlist(mk_list(1000000)), oops]] end, L2BTrap),
1686    error_after_yield(badarg, binary, list_to_bin, 1, fun () -> [[mk_list(1000000), oops]] end, L2BTrap),
1687
1688    B2TTrap = {erts_internal, binary_to_term_trap, 1},
1689
1690    error_after_yield(badarg, erlang, binary_to_term, 1, fun () -> [error_after_yield_bad_ext_term()] end, B2TTrap),
1691    error_after_yield(badarg, erlang, binary_to_term, 2, fun () -> [error_after_yield_bad_ext_term(), [safe]] end, B2TTrap),
1692
1693    case erlang:system_info(wordsize) of
1694	4 ->
1695	    SysLimitSz = 1 bsl 32,
1696	    error_after_yield(system_limit, erlang, list_to_binary, 1, fun () -> [[huge_iolist(SysLimitSz), $x]] end, L2BTrap),
1697	    error_after_yield(system_limit, erlang, iolist_to_binary, 1, fun () -> [[huge_iolist(SysLimitSz), $x]] end, L2BTrap),
1698	    error_after_yield(system_limit, erlang, list_to_bitstring, 1, fun () -> [[huge_iolist(SysLimitSz), $x]] end, L2BTrap),
1699	    error_after_yield(system_limit, binary, list_to_bin, 1, fun () -> [[huge_iolist(SysLimitSz), $x]] end, L2BTrap);
1700	8 ->
1701	    % Takes waaaay to long time to test system_limit on 64-bit archs...
1702	    ok
1703    end,
1704    ok.
1705
1706error_after_yield(Type, M, F, AN, AFun, TrapFunc) ->
1707    io:format("Testing ~p for ~p:~p/~p~n", [Type, M, F, AN]),
1708    Tracer = self(),
1709    {Pid, Mon} = spawn_monitor(fun () ->
1710				       A = AFun(),
1711				       try
1712					   erlang:yield(),
1713					   erlang:trace(self(),true,[running,{tracer,Tracer}]),
1714					   apply(M, F, A),
1715					   exit({unexpected_success, {M, F, A}})
1716				       catch
1717					   error:Type:Stk ->
1718					       erlang:trace(self(),false,[running,{tracer,Tracer}]),
1719					       %% We threw the exception from the native
1720					       %% function we trapped to, but we want
1721					       %% the BIF that originally was called
1722					       %% to appear in the stack trace.
1723					       [{M, F, A, _} | _] = Stk
1724				       end
1725			       end),
1726    receive
1727	{'DOWN', Mon, process, Pid, Reason} ->
1728	    normal = Reason
1729    end,
1730    TD = erlang:trace_delivered(Pid),
1731    receive
1732	{trace_delivered, Pid, TD} ->
1733	    NoYields = error_after_yield_sched(Pid, TrapFunc, 0),
1734	    io:format("No of yields: ~p~n", [NoYields]),
1735	    true =  NoYields > 2
1736    end,
1737    ok.
1738
1739error_after_yield_sched(P, TrapFunc, N) ->
1740    receive
1741	{trace, P, out, TrapFunc} ->
1742	    receive
1743		{trace, P, in, TrapFunc} ->
1744		    error_after_yield_sched(P, TrapFunc, N+1)
1745	    after 0 ->
1746		    exit(trap_sched_mismatch)
1747	    end;
1748	{trace, P, out, Func} ->
1749	    receive
1750		{trace, P, in, Func} ->
1751		    error_after_yield_sched(P, TrapFunc, N)
1752	    after 0 ->
1753		    exit(other_sched_mismatch)
1754	    end
1755    after 0 ->
1756	    N
1757    end.
1758
1759error_after_yield_bad_ext_term() ->
1760    TupleSz = 2000000,
1761    <<131, % Version magic
1762      AtomExt/binary>> = term_to_binary(an_atom_we_use_for_this),
1763    BadAtomExt = [100, %% ATOM_EXT
1764		  255, 255, % Invalid size of 65535 bytes
1765		  "oops"],
1766
1767    %% Produce a large tuple where the last element is invalid
1768    list_to_binary([131, %% Version magic
1769		    105, %% LARGE_TUPLE_EXT
1770		    <<TupleSz:32/big>>, %% Tuple size
1771		    lists:duplicate(TupleSz-1, AtomExt), %% Valid atoms
1772		    BadAtomExt]). %% Invalid atom at the end
1773
1774cmp_old_impl(Config) when is_list(Config) ->
1775    %% This test was originally a comparison with the non yielding
1776    %% implementation in R16B. Since OTP 22 we can't talk distribution with such
1777    %% old nodes (< 19). The test case it kept but compares with previous major
1778    %% version for semantic regression test.
1779    Cookie = atom_to_list(erlang:get_cookie()),
1780    Rel = (integer_to_list(list_to_integer(erlang:system_info(otp_release)) - 1)
1781           ++ "_latest"),
1782    case test_server:is_release_available(Rel) of
1783	false ->
1784	    {skipped, "No OTP "++Rel++" available"};
1785	true ->
1786	    {ok, Node} = test_server:start_node(list_to_atom(atom_to_list(?MODULE)++"_"++Rel),
1787				       peer,
1788				       [{args, " -setcookie "++Cookie},
1789					{erl, [{release, Rel}]}]),
1790
1791	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(1))]}),
1792	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(10))]}),
1793	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(100))]}),
1794	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(1000))]}),
1795	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(10000))]}),
1796	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(100000))]}),
1797	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(1000000))]}),
1798	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list(10000000))]}),
1799	    cmp_node(Node, {erlang, list_to_binary, [list2iolist(mk_list_lb(10000000))]}),
1800
1801	    cmp_node(Node, {erlang, binary_to_list, [list_to_binary(mk_list(1))]}),
1802	    cmp_node(Node, {erlang, binary_to_list, [list_to_binary(mk_list(10))]}),
1803	    cmp_node(Node, {erlang, binary_to_list, [list_to_binary(mk_list(100))]}),
1804	    cmp_node(Node, {erlang, binary_to_list, [list_to_binary(mk_list(1000))]}),
1805	    cmp_node(Node, {erlang, binary_to_list, [list_to_binary(mk_list(10000))]}),
1806	    cmp_node(Node, {erlang, binary_to_list, [list_to_binary(mk_list(100000))]}),
1807	    cmp_node(Node, {erlang, binary_to_list, [list_to_binary(mk_list(1000000))]}),
1808	    cmp_node(Node, {erlang, binary_to_list, [list_to_binary(mk_list(10000000))]}),
1809
1810	    cmp_node(Node, {erlang, list_to_bitstring, [list2bitstrlist(mk_list(1))]}),
1811	    cmp_node(Node, {erlang, list_to_bitstring, [list2bitstrlist(mk_list(10))]}),
1812	    cmp_node(Node, {erlang, list_to_bitstring, [list2bitstrlist(mk_list(100))]}),
1813	    cmp_node(Node, {erlang, list_to_bitstring, [list2bitstrlist(mk_list(1000))]}),
1814	    cmp_node(Node, {erlang, list_to_bitstring, [list2bitstrlist(mk_list(10000))]}),
1815	    cmp_node(Node, {erlang, list_to_bitstring, [list2bitstrlist(mk_list(100000))]}),
1816	    cmp_node(Node, {erlang, list_to_bitstring, [list2bitstrlist(mk_list(1000000))]}),
1817	    cmp_node(Node, {erlang, list_to_bitstring, [list2bitstrlist(mk_list(10000000))]}),
1818
1819	    cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(1)))]}),
1820	    cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(10)))]}),
1821	    cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(100)))]}),
1822	    cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(1000)))]}),
1823	    cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(10000)))]}),
1824	    cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(100000)))]}),
1825	    cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(1000000)))]}),
1826	    cmp_node(Node, {erlang, bitstring_to_list, [list_to_bitstring(list2bitstrlist(mk_list(10000000)))]}),
1827
1828	    test_server:stop_node(Node),
1829
1830	    ok
1831    end.
1832
1833%% OTP-16265
1834%% This testcase is mainly targeted toward --enable-sharing-preserving.
1835sub_bin_copy(Config) when is_list(Config) ->
1836    Papa = self(),
1837    Echo = spawn_link(fun() -> echo(Papa) end),
1838    HeapBin = list_to_binary(lists:seq(1,3)),
1839    sub_bin_copy_1(HeapBin, Echo),
1840    ProcBin = list_to_binary(lists:seq(1,65)),
1841    sub_bin_copy_1(ProcBin, Echo),
1842    unlink(Echo),
1843    exit(Echo, kill),
1844    ok.
1845
1846sub_bin_copy_1(RealBin, Echo) ->
1847    Bits = bit_size(RealBin) - 1,
1848    <<SubBin:Bits/bits, _/bits>> = RealBin,
1849
1850    %% Send (copy) messages consisting of combinations of both
1851    %% the SubBin and the RealBin it refers to.
1852    [begin
1853         Echo ! Combo,
1854         {_, Combo} = {Combo, receive M -> M end}
1855     end
1856     || Len <- lists:seq(2,5), Combo <- combos([RealBin, SubBin], Len)],
1857    ok.
1858
1859combos(_, 0) ->
1860    [[]];
1861combos(Elements, Len) ->
1862    [[E | C] || E <- Elements, C <- combos(Elements,Len-1)].
1863
1864echo(Papa) ->
1865    receive M -> Papa ! M end,
1866    echo(Papa).
1867
1868
1869%% Utilities.
1870
1871huge_iolist(Lim) ->
1872    Sz = 1024,
1873    huge_iolist(list_to_binary(mk_list(Sz)), Sz, Lim).
1874
1875huge_iolist(X, Sz, Lim) when Sz >= Lim ->
1876    X;
1877huge_iolist(X, Sz, Lim) ->
1878    huge_iolist([X, X], Sz*2, Lim).
1879
1880cmp_node(Node, {M, F, A}) ->
1881    Res = rpc:call(Node, M, F, A),
1882    Res = apply(M, F, A),
1883    ok.
1884
1885make_sub_binary(Bin) when is_binary(Bin) ->
1886    {_,B} = split_binary(list_to_binary([0,1,3,Bin]), 3),
1887    B;
1888make_sub_binary(List) ->
1889    make_sub_binary(list_to_binary(List)).
1890
1891make_unaligned_sub_binary(Bin0) when is_binary(Bin0) ->
1892    Bin1 = <<0:3,Bin0/binary,31:5>>,
1893    Sz = size(Bin0),
1894    <<0:3,Bin:Sz/binary,31:5>> = id(Bin1),
1895    Bin;
1896make_unaligned_sub_binary(List) ->
1897    make_unaligned_sub_binary(list_to_binary(List)).
1898
1899%% Add 1 bit to the size of the binary.
1900bit_sized_binary(Bin0) ->
1901    Bin = <<Bin0/binary,1:1>>,
1902    BitSize = bit_size(Bin),
1903    BitSize = 8*size(Bin) + 1,
1904    Bin.
1905
1906unaligned_sub_bin(Bin, 0) -> Bin;
1907unaligned_sub_bin(Bin0, Offs) ->
1908    F = rand:uniform(256),
1909    Roffs = 8-Offs,
1910    Bin1 = <<F:Offs,Bin0/binary,F:Roffs>>,
1911    Sz = size(Bin0),
1912    <<_:Offs,Bin:Sz/binary,_:Roffs>> = id(Bin1),
1913    Bin.
1914
1915id(I) -> I.
1916
1917
1918%% Stress binary_to_term with different initial reductions
1919binary_to_term_stress(Bin) ->
1920    binary_to_term_stress(Bin, no_opts).
1921
1922binary_to_term_stress(Bin, Opts) ->
1923    Reds = get_reds(),
1924    T = b2t(erlang:system_info(context_reductions),
1925	    Bin, Opts, catch_binary_to_term(Bin, Opts)),
1926    set_reds(Reds),
1927    T = case Opts of
1928	    no_opts -> binary_to_term(Bin);
1929	    _ ->       binary_to_term(Bin,Opts)
1930	end.
1931
1932catch_binary_to_term(Bin, no_opts) ->
1933    try binary_to_term(Bin)
1934    catch
1935	error:badarg -> binary_to_term_throws_badarg
1936    end;
1937catch_binary_to_term(Bin, Opts) ->
1938    try binary_to_term(Bin, Opts)
1939    catch
1940	error:badarg -> binary_to_term_throws_badarg
1941    end.
1942
1943b2t(0, _Bin, _Opts, Term) ->
1944    Term;
1945b2t(Reds, Bin, Opts, Term) ->
1946    set_reds(Reds),
1947    Term = catch_binary_to_term(Bin,Opts),
1948    b2t(Reds div 3, Bin, Opts, Term).
1949
1950set_reds(Reds) ->
1951    try	erts_debug:set_internal_state(reds_left, Reds)
1952    catch
1953	error:undef ->
1954	    erts_debug:set_internal_state(available_internal_state, true),
1955	    set_reds(Reds)
1956    end.
1957
1958get_reds() ->
1959    try	erts_debug:get_internal_state(reds_left)
1960    catch
1961	error:undef ->
1962	    erts_debug:set_internal_state(available_internal_state, true),
1963	    get_reds()
1964    end.
1965
1966-define(LARGE_BIN, (512*1024+10)).
1967-define(LARGE_BIN_LIM, (1024*1024)).
1968
1969mk_list(0, Acc) ->
1970    Acc;
1971mk_list(Sz, Acc) ->
1972    mk_list(Sz-1, [$A+(Sz band 63) | Acc]).
1973
1974mk_list(Sz) when Sz >= ?LARGE_BIN_LIM ->
1975    SzLeft = Sz - ?LARGE_BIN,
1976    SzHd = SzLeft div 2,
1977    SzTl = SzLeft - SzHd,
1978    [mk_list(SzHd, []), erlang:list_to_binary(mk_list(?LARGE_BIN, [])), mk_list(SzTl, [])];
1979mk_list(Sz) ->
1980    mk_list(Sz, []).
1981
1982mk_list_lb(Sz) when Sz >= ?LARGE_BIN_LIM ->
1983    SzLeft = Sz - ?LARGE_BIN,
1984    SzHd = SzLeft div 2,
1985    SzTl = SzLeft - SzHd,
1986    [mk_list(SzHd, []), erlang:list_to_binary(mk_list(?LARGE_BIN, [])), mk_list(SzTl, [])];
1987mk_list_lb(Sz) ->
1988    mk_list(Sz, []).
1989
1990
1991list2iolist(List) ->
1992    list2iolist(List, []).
1993
1994list2iolist([], Acc) ->
1995    Acc;
1996list2iolist([X0, X1, X2, X3, X4, X5 | Xs], Acc) when is_integer(X0), 0 =< X0, X0 < 256,
1997						     is_integer(X1), 0 =< X1, X1 < 256,
1998						     is_integer(X2), 0 =< X2, X2 < 256,
1999						     is_integer(X3), 0 =< X3, X3 < 256,
2000						     is_integer(X4), 0 =< X4, X4 < 256,
2001						     is_integer(X5), 0 =< X5, X5 < 256 ->
2002    NewAcc = case (X0+X1+X2+X3+X4+X5) band 3 of
2003		 0 ->
2004		     [Acc, [[[[[[[[[[[[X0,[],<<"">>,X1]]]]]]]]],[X2,X3]],[],[],[],[],X4],X5]];
2005		 1 ->
2006		     [Acc, [], erlang:list_to_binary([X0, X1, X2, X3, X4, X5])];
2007		 2 ->
2008		     [Acc, [[[[X0|erlang:list_to_binary([X1])],[X2|erlang:list_to_binary([X3])],[X4|erlang:list_to_binary([X5])]]]|<<"">>]];
2009		 3 ->
2010		     [Acc, X0, X1, X2, <<"">>, [], X3, X4 | erlang:list_to_binary([X5])]
2011	     end,
2012    list2iolist(Xs, NewAcc);
2013list2iolist([X | Xs], Acc) ->
2014    list2iolist(Xs, [Acc,X]).
2015
2016list2bitstrlist(List) ->
2017    [list2bitstrlist(List, []), <<4:7>>].
2018
2019list2bitstrlist([], Acc) ->
2020    Acc;
2021list2bitstrlist([X0, X1, X2, X3, X4, X5 | Xs], Acc) when is_integer(X0), 0 =< X0, X0 < 256,
2022						     is_integer(X1), 0 =< X1, X1 < 256,
2023						     is_integer(X2), 0 =< X2, X2 < 256,
2024						     is_integer(X3), 0 =< X3, X3 < 256,
2025						     is_integer(X4), 0 =< X4, X4 < 256,
2026						     is_integer(X5), 0 =< X5, X5 < 256 ->
2027    NewAcc = case (X0+X1+X2+X3+X4+X5) band 3 of
2028		 0 ->
2029		     [Acc, [[[[[[[[[[[[X0,[],<<"">>,X1]]]]]]]]],[X2,X3]],[],[],[],[],X4],X5]];
2030		 1 ->
2031		     [Acc, [], <<X0:X1>>, <<X2:X3>>, <<X4:X5>>];
2032		 2 ->
2033		     [Acc, [[[[X0|<<X1:X2>>],X3]],[X4|erlang:list_to_binary([X5])]|<<"">>]];
2034		 3 ->
2035		     [Acc, X0, X1, X2, <<"">>, [], X3, X4 | erlang:list_to_binary([X5])]
2036	     end,
2037    list2bitstrlist(Xs, NewAcc);
2038list2bitstrlist([X | Xs], Acc) ->
2039    list2bitstrlist(Xs, [Acc,X]).
2040