1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2006-2018. 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%% Originally based on Per Gustafsson's test suite.
21%%
22
23-module(bs_bincomp_SUITE).
24
25-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
26	 init_per_group/2,end_per_group/2,
27	 byte_aligned/1,bit_aligned/1,extended_byte_aligned/1,
28	 extended_bit_aligned/1,mixed/1,filters/1,trim_coverage/1,
29	 nomatch/1,sizes/1,general_expressions/1,
30         no_generator/1,zero_pattern/1,multiple_segments/1]).
31
32-include_lib("common_test/include/ct.hrl").
33
34suite() -> [{ct_hooks,[ts_install_cth]}].
35
36all() ->
37    [byte_aligned, bit_aligned, extended_byte_aligned,
38     extended_bit_aligned, mixed, filters, trim_coverage,
39     nomatch, sizes, general_expressions,
40     no_generator, zero_pattern, multiple_segments].
41
42groups() ->
43    [].
44
45init_per_suite(Config) ->
46    test_lib:recompile(?MODULE),
47    Config.
48
49end_per_suite(_Config) ->
50    ok.
51
52init_per_group(_GroupName, Config) ->
53	Config.
54
55end_per_group(_GroupName, Config) ->
56	Config.
57
58byte_aligned(Config) when is_list(Config) ->
59    cs_init(),
60    <<"abcdefg">> = cs(<< <<(X+32)>> || <<X>> <= <<"ABCDEFG">> >>),
61    <<"AxyzBxyzCxyz">> = cs(<< <<X, "xyz">> || <<X>> <= <<"ABC">> >>),
62    <<1:32/little,2:32/little,3:32/little,4:32/little>> =
63	cs(<< <<X:32/little>> || <<X:32>> <= <<1:32,2:32,3:32,4:32>> >>),
64    cs(<<1:32/little,2:32/little,3:32/little,4:32/little>> =
65	   << <<X:32/little>> || <<X:16>> <= <<1:16,2:16,3:16,4:16>> >>),
66    cs_end().
67
68bit_aligned(Config) when is_list(Config) ->
69    cs_init(),
70    <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> =
71	cs(<< <<(X+32):7>> || <<X>> <= <<"ABCDEFG">> >>),
72    <<"ABCDEFG">> = cs(<< <<(X-32)>> || <<X:7>> <= id(<<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>) >>),
73    <<1:31/little,2:31/little,3:31/little,4:31/little>> =
74	cs(<< <<X:31/little>> || <<X:31>> <= <<1:31,2:31,3:31,4:31>> >>),
75    <<1:31/little,2:31/little,3:31/little,4:31/little>> =
76	cs(<< <<X:31/little>> || <<X:15>> <= <<1:15,2:15,3:15,4:15>> >>),
77    cs_end().
78
79extended_byte_aligned(Config) when is_list(Config) ->
80    cs_init(),
81    <<"abcdefg">> = cs(<< <<(X+32)>> || X <- "ABCDEFG" >>),
82    "abcdefg" = [(X+32) || <<X>> <= <<"ABCDEFG">>],
83    <<1:32/little,2:32/little,3:32/little,4:32/little>> =
84	cs(<< <<X:32/little>> || X <- [1,2,3,4] >>),
85    [256,512,768,1024] =
86	[X || <<X:16/little>> <= <<1:16,2:16,3:16,4:16>>],
87    cs_end().
88
89extended_bit_aligned(Config) when is_list(Config) ->
90    cs_init(),
91    <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> =
92	cs(<< <<(X+32):7>> || X <- "ABCDEFG" >>),
93    "ABCDEFG" = [(X-32) || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>],
94    <<1:31/little,2:31/little,3:31/little,4:31/little>> =
95	cs(<< <<X:31/little>> || X <- [1,2,3,4] >>),
96    [256,512,768,1024] =
97	[X || <<X:15/little>> <= <<1:15,2:15,3:15,4:15>>],
98    cs_end().
99
100mixed(Config) when is_list(Config) ->
101    cs_init(),
102    <<2,3,3,4,4,5,5,6>> =
103	cs(<< <<(X+Y)>> || <<X>> <= <<1,2,3,4>>, <<Y>> <= <<1,2>> >>),
104    <<2,3,3,4,4,5,5,6>> =
105	cs(<< <<(X+Y)>> || <<X>> <= <<1,2,3,4>>, Y <- [1,2] >>),
106    <<2,3,3,4,4,5,5,6>> =
107	cs(<< <<(X+Y)>> || X <- [1,2,3,4], Y <- [1,2] >>),
108    One = id([1,2,3,4]),
109    Two = id([1,2]),
110    <<2,3,3,4,4,5,5,6>> =
111	cs(<< <<(X+Y)>> || X <- One, Y <- Two >>),
112    [2,3,3,4,4,5,5,6] =
113	[(X+Y) || <<X>> <= <<1,2,3,4>>, <<Y>> <= <<1,2>>],
114    [2,3,3,4,4,5,5,6] =
115	[(X+Y) || <<X>> <= <<1,2,3,4>>, Y <- [1,2]],
116    <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
117	cs(<< <<(X+Y):3>> || <<X:3>> <= <<1:3,2:3,3:3,4:3>>,
118                              <<Y:3>> <= <<1:3,2:3>> >>),
119    <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
120	cs(<< <<(X+Y):3>> || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, Y <- [1,2] >>),
121    <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
122	cs(<< <<(X+Y):3>> || X <- [1,2,3,4], Y <- [1,2] >>),
123    <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> =
124	cs_default(<< <<(X+Y):3>> || {X,Y} <- [{1,1},{1,2},{2,1},{2,2},
125                                               {3,1},{3,2},{4,1},{4,2}] >>),
126    [2,3,3,4,4,5,5,6] =
127	[(X+Y) || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, <<Y:3>> <= <<1:3,2:3>>],
128    [2,3,3,4,4,5,5,6] =
129	[(X+Y) || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, {_,Y} <- [{a,1},{b,2}]],
130
131    %% OTP-16899: Nested binary comprehensions would fail to load.
132    <<0,1,0,2,0,3,99>> = mixed_nested([1,2,3]),
133
134    <<1>> = cs_default(<< <<X>> || L <- [[1]], X <- L >>),
135
136    %% The compiler would crash in v3_kernel.
137    <<42:32,75:32,253:32,(42 bsl 8 bor 75):32>> =
138        cs_default(mixed_size(id([8,16]), <<42,75,253>>)),
139
140    silly_lc_bc(5),
141
142    gen_data(0),
143    gen_data(256),
144    gen_data(512),
145
146    <<1,2,3>> = cs_default(match_context_1(<<1,2,3>>)),
147    <<4,5,6>> = cs_default(match_context_2(<<4,5,6>>)),
148
149    <<255>> = over_complex_generator(),
150    {'EXIT',_} = catch float_segment_size(),
151
152    cs_end().
153
154mixed_nested(L) ->
155    << << << << E:16 >> || E <- L >> || true >>/binary, 99:(id(8))>>.
156
157mixed_size(List, Bin) ->
158    << <<X:32>> || Size <- List, <<X:Size>> <= Bin >>.
159
160silly_lc_bc(N) when N > 0 ->
161    Bin = iolist_to_binary(silly_lc(N)),
162    Bin = cs(silly_bc(N)),
163    Size = byte_size(Bin),
164    Size = 5 bsl N,
165    silly_lc_bc(N - 1);
166silly_lc_bc(_) -> ok.
167
168silly_bc(0) ->
169    <<0, 1, 2, 3, 4>>;
170silly_bc(N) ->
171    << <<X, X>> || <<X>> <= silly_bc(N - 1) >>.
172
173silly_lc(0) ->
174    [0, 1, 2, 3, 4];
175silly_lc(N) ->
176    [[X, X] || X <- silly_lc(N - 1)].
177
178gen_data(Size) ->
179    Data = cs(<< <<C>> || C <- lists:seq(0, Size-1) >>),
180    Data = << <<C>> || _ <- lists:seq(1, Size div 256),
181                       C <- lists:seq(0, 255) >>.
182
183match_context_1(<<B/binary>>) ->
184    << <<V>> || <<V>> <= B >>.
185
186match_context_2(<<B/binary>>) ->
187    do_match_context_2(B).
188
189do_match_context_2(B) ->
190    << <<V>> || <<V>> <= B >>.
191
192%% Would crash beam_ssa_bc_size when the no_copt option was given.
193over_complex_generator() ->
194    <<
195      <<255>> ||
196        <<0:2>> <= <<0:2>>,
197        <<_:8>> <=
198            case true of
199                true ->
200                    <<8>>;
201                [6.6 | bad_tail] ->
202                    ok;
203                [3 | 4] ->
204                    error
205            end
206    >>.
207
208float_segment_size() ->
209    try
210        V = 0.79
211    of
212        _ ->
213            %% Would crash beam_ssa_bc_size when trying to
214            %% interpret V * U = 0.79 * 8 as a size.
215            <<
216              0 || <<5.9:V/unit:8-float>> <= 42
217            >>
218    catch
219        _:_ ->
220            error
221    end.
222
223filters(Config) when is_list(Config) ->
224    cs_init(),
225    <<"BDF">> =
226	cs_default(<< <<(X-32)>> ||
227		       <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>,
228		       X rem 2 == 0>>),
229    <<"abc">> = cs_default(<< <<(X+32)>> ||
230			       X <- "ABCDEFG",
231			       is_less_than(X, $D)>>),
232    <<"efg">> = cs_default(<< <<(X+32)>> ||
233			       X <- "ABCDEFG",
234			       not is_less_than(X, $E)>>),
235    <<"b">> = cs_default(<< <<(X+32)>> ||
236			     X <- "ABCDEFG",
237			     is_less_than(X, $D),
238			     X rem 2 == 0>>),
239    <<"eg">> = cs_default(<< <<(X+32)>> ||
240			      X <- "ABCDEFG",
241			      not is_less_than(X, $E),
242			      X rem 2 == 1>>),
243    <<1,3>> = cs_default(<< <<(length(L))>> ||
244                             L <- [[],[a],[],[x,y,z]],
245                             case L of
246                                 [] -> false;
247                                 [_|_] -> true
248                             end >>),
249    <<77,42>> = cs_default(<< <<B>> || <<B>> <- [<<77>>,<<1,2>>,<<42>>] >>),
250
251    %% Filtering by a non-matching pattern.
252    <<"abd">> = cs_default(<< <<X:8>> ||
253			       <<0:1,X:7>> <= <<$a:8,$b:8,1:1,$c:7,$d:8,
254						1:1,$e:7,0:4>> >>),
255
256    <<42,42>> = cs_default(<< <<42:8>> || 42 <- [1,2,3,42,43,42] >>),
257    cs_end().
258
259is_less_than(X, C) when X < C -> true;
260is_less_than(_, _) -> false.
261
262trim_coverage(Config) when is_list(Config) ->
263    <<0,0,0,2,0,0,5,48,0,11,219,174,0,0,0,0>> = coverage_materialiv(a, b, {1328,777134}),
264    <<67,40,0,0,66,152,0,0,69,66,64,0>> = coverage_trimmer([42,19,777]),
265    <<0,0,2,43,0,0,3,9,0,0,0,3,64,8,0,0,0,0,0,0,
266	   64,68,0,0,0,0,0,0,192,171,198,0,0,0,0,0>> =
267	coverage_lightfv(555, 777, {3.0,40.0,-3555.0}),
268    <<"abcabc">> = coverage_strange(0, <<"abc">>),
269    ok.
270
271coverage_materialiv(A, B, Params) ->
272    A = id(A),
273    B = id(B),
274    <<(tuple_size(Params)):32,
275     (<< <<C:32>> || C <- tuple_to_list(Params)>>)/binary,
276     0:(((1+tuple_size(Params)) rem 2)*32)>>.
277
278coverage_lightfv(Light, Pname, Params) ->
279    id(<<Light:32,Pname:32,(size(Params)):32,
280	(<< <<C:64/float>> || C <- tuple_to_list(Params)>>)/binary,
281	0:(((1+size(Params)) rem 2)*32)>>).
282
283coverage_trimmer(Params) ->
284    X = id(0),
285    Y = id(1),
286    id({X,Y}),
287    << <<(begin {A,B,D} = id({C,C,C}), id(0),
288		coverage_summer(A, B, C, D) end):32/float>> ||
289	C <- Params >>.
290
291coverage_summer(A, B, C, D) -> A+B+C+D.
292
293coverage_strange(V, Bin) ->
294    <<
295      << <<X>> || <<X/utf8>> <= Bin >>/bits,
296      << <<Y>> || <<Y>> <= Bin>>:
297      case V of
298          V ->
299              3;
300          0 ->
301              receive
302                  whatever ->
303                      1
304              end
305      end/bytes>>.
306
307nomatch(Config) when is_list(Config) ->
308    Bin = id(<<1,2,3,4,5>>),
309    <<>> = << <<X:8>> || X = {_,_} = [_|_] <- [1,2,3] >>,
310    [] = [X || <<X:all/binary>> <= Bin],
311    [] = [X || <<X:bad/binary>> <= Bin],
312    <<>> = << <<X:32>> || <<X:all/binary>> <= Bin >>,
313    <<>> = << <<X:32>> || <<X:bad/binary>> <= Bin >>,
314
315    <<>> = << <<"a">> || <<_:1/float>> <= Bin>>,
316
317    NaN = <<(-1):32>>,
318    <<>> = << <<"a">> || <<_:32/float>> <= NaN >>,
319
320    <<1:32,2:32,3:32>> = nomatch_1(<<1,2,3>>, 8),
321    <<>> = nomatch_1(<<1,2,3>>, bad),
322
323    <<>> = << <<>> || <<_:8>> <= <<>> >>,
324
325    ok.
326
327nomatch_1(Bin, Size) ->
328    << <<X:32>> || <<X:Size>> <= Bin >>.
329
330sizes(Config) when is_list(Config) ->
331    cs_init(),
332    Fun0 = fun(List) ->
333		   cs(<< <<E:8>> || E <- List >>)
334	   end,
335    <<>> = Fun0([]),
336    <<1>> = Fun0([1]),
337    <<1,2>> = Fun0([1,2]),
338    <<1,2,3>> = Fun0([1,2,3]),
339
340    Fun1 = fun(List) ->
341		   cs(<< <<E:16>> || E <- List >>)
342	   end,
343    <<>> = Fun1([]),
344    <<1:16>> = Fun1([1]),
345    <<1:16,2:16>> = Fun1([1,2]),
346    <<1:16,2:16,3:16>> = Fun1([1,2,3]),
347
348    Fun2 = fun(List) ->
349		   cs(<< <<E:4>> || E <- List >>)
350	   end,
351    <<>> = Fun2([]),
352    <<1:4>> = Fun2([1]),
353    <<1:4,13:4>> = Fun2([1,13]),
354    <<1:4,13:4,7:4>> = Fun2([1,13,7]),
355    <<0:1000/unit:8>> = Fun2(lists:duplicate(2000, 0)),
356
357    Fun3 = fun(List) ->
358		   cs(<< <<E:3>> || E <- List >>)
359	   end,
360    <<>> = Fun3([]),
361    <<40,177,29:5>> = Fun3([1,2,1,3,0,7,5]),
362    <<0:512/unit:3>> = Fun3(lists:duplicate(512, 0)),
363
364    Fun4 = fun(List, Size) ->
365		   cs(<< <<E:Size>> || E <- List >>)
366	   end,
367    <<>> = Fun4([], 8),
368    <<42:6>> = Fun4([42], 6),
369    <<42:16>> = Fun4([42], 16),
370
371    Fun5 = fun(List, Sz1, Sz2, Sz3) ->
372		   cs(<< <<E:Sz1,(E+1):Sz2/unit:8,(E+2):Sz3/unit:8>> || E <- List >>)
373	   end,
374    <<>> = Fun5([], 1, 1, 1),
375    <<7:3,8:40,9:56>> = Fun5([7], 3, 5, 7),
376
377    Fun5a = fun(List, Sz1, Sz2, Sz3) ->
378                    cs(<< <<"abc",E:Sz1,(E+1):Sz2/unit:8,"qqq",(E+2):Sz3/unit:8,"xyz">> ||
379                          E <- List >>)
380	   end,
381    <<>> = Fun5a([], 1, 1, 1),
382    <<"abc",7:3,8:40,"qqq",9:56,"xyz">> = Fun5a([7], 3, 5, 7),
383
384    Fun6 = fun(List, Size) ->
385		   cs(<< <<E:8,(E+1):Size>> || E <- List >>)
386	   end,
387    <<>> = Fun6([], 42),
388    <<42,43:20>> = Fun6([42], 20),
389
390    %% Binary generators.
391
392    Fun10 = fun(Bin) ->
393		    cs(<< <<E:16>> || <<E:8>> <= id(Bin) >>)
394            end,
395    <<>> = Fun10(<<>>),
396    <<1:16>> = Fun10(<<1>>),
397    <<1:16,2:16>> = Fun10(<<1,2>>),
398
399    Fun11 = fun(Bin) ->
400		    cs(<< <<E:8>> || <<E:16>> <= id(Bin) >>)
401            end,
402    <<>> = Fun11(<<>>),
403    <<1>> = Fun11(<<1:16>>),
404    <<1,2>> = Fun11(<<1:16,2:16>>),
405    <<1,2>> = Fun11(<<1:16,2:16,0:1>>),
406    <<1,2>> = Fun11(<<1:16,2:16,0:7>>),
407    <<1,2>> = Fun11(<<1:16,2:16,42:8>>),
408    <<1,2>> = Fun11(<<1:16,2:16,42:9>>),
409    <<1,2>> = Fun11(<<1:16,2:16,255:15>>),
410
411    Fun12 = fun(Bin, Sz1, Sz2) ->
412		    cs(<< <<E:Sz1>> || <<E:Sz2>> <= id(Bin) >>)
413	    end,
414    <<>> = Fun12(<<>>, 1, 1),
415    Binary = list_to_binary(lists:seq(0, 255)),
416    Binary = Fun12(Binary, 1, 1),
417    Binary = Fun12(Binary, 4, 4),
418    Binary = Fun12(Binary, 8, 8),
419    <<17:9,19:9>> = Fun12(<<17:6,19:6>>, 9, 6),
420
421    Fun13 = fun(Sz) ->
422		    cs(<< <<C:8>> || <<C:4>> <= <<1:4,2:4,3:4,0:Sz>> >>)
423   	    end,
424    <<1,2,3>> = Fun13(0),
425    <<1,2,3,0>> = Fun13(4),
426    <<1,2,3,0>> = Fun13(5),
427    <<1,2,3,0>> = Fun13(6),
428    <<1,2,3,0>> = Fun13(7),
429    <<1,2,3,0,0>> = Fun13(8),
430
431    <<0:3>> = cs_default(<< <<0:S>> || S <- [0,1,2] >>),
432    <<0:3>> = cs_default(<< <<0:S>> || <<S>> <= <<0,1,2>> >>),
433
434    Fun14 = fun(L, B) ->
435                    cs_default(<< <<X:32>> || Size <- L, <<X:Size>> <= B >>)
436            end,
437    <<$a:32,$b:32,$c:32,($a bsl 8 bor $b):32>> = Fun14([8,16], <<"abc">>),
438    <<$a:32,$b:32,$c:32>> = Fun14([8,bad], <<"abc">>),
439
440    {'EXIT',_} = (catch << <<C:4>> || <<C:8>> <= {1,2,3} >>),
441
442    cs_end(),
443    ok.
444
445-define(BAD(E),   {'EXIT',{badarg,_}} = (catch << (E) || _ <- [1,2,3] >>)).
446-define(BAD_V(E), {'EXIT',{badarg,_}} = (catch << (E) || I <- [1,2,3] >>)).
447
448general_expressions(_) ->
449    cs_init(),
450
451    <<1,2,3>> = cs(<< begin <<1,2,3>> end || _ <- [1] >>),
452    <<"abc">> = cs(<< begin <<"abc">> end || _ <- [1] >>),
453    <<1,2,3>> = cs_default(<< begin
454                                  I = <<(I0+1)>>,
455                                  id(I)
456                              end || <<I0>> <= <<0,1,2>> >>),
457    <<1,2,3>> = cs_default(<< I || I <- [<<1,2>>,<<3>>] >>),
458    <<1,2,3>> = cs_default(<< (id(<<I>>)) || I <- [1,2,3] >>),
459    <<2,4>> = cs_default(<< case I rem 2 of
460                                0 -> <<I>>;
461                                1 -> <<>>
462                            end || I <- [1,2,3,4,5] >>),
463    <<2,3,4,5,6,7>> = cs_default(<< << (id(<<J>>)) || J <- [2*I,2*I+1] >> ||
464                                     I <- [1,2,3] >>),
465    <<1,2,2,3,4,4>> = cs_default(<< if
466                                        I rem 2 =:= 0 -> <<I,I>>;
467                                        true -> <<I>>
468                                    end || I <- [1,2,3,4] >>),
469    self() ! <<42>>,
470    <<42>> = cs_default(<< receive B -> B end || _ <- [1] >>),
471    <<10,5,3>> = cs_default(<< try
472                                   <<(10 div I)>>
473                               catch _:_ ->
474                                       <<>>
475                               end || I <- [0,1,2,3] >>),
476
477    <<3:4,16#A:4,7:4>> = cs(hstring_to_bitstring("3A7")),
478    <<0:3,1:3,2:3,3:3,4:3,5:3,6:3,7:3>> = cs(encode_chars_compact_map("ABCDEFGH", id(3), id({$A,8}))),
479
480    cs_end(),
481
482    %% Failing expressions.
483    ?BAD(bad_atom),
484    ?BAD(42),
485    ?BAD(42.0),
486    ?BAD_V({ok,I}),
487    ?BAD_V([I]),
488    ?BAD_V(fun() -> I end),
489
490    ok.
491
492hstring_to_bitstring(L) ->
493    << <<(hex_to_int(D)):4>> || D <- L >>.
494
495hex_to_int(D) when $0 =< D, D =< $9 -> D - $0;
496hex_to_int(D) when $A =< D, D =< $F -> D - ($A - 10).
497
498encode_chars_compact_map(Val, NumBits, {Lb,Limit}) ->
499    << <<(enc_char_cm(C, Lb, Limit)):NumBits>> || C <- Val >>.
500
501enc_char_cm(C0, Lb, Limit) ->
502    C = C0 - Lb,
503    if
504	0 =< C, C < Limit ->
505	    C;
506	true ->
507            error(illegal)
508    end.
509
510-undef(BAD).
511
512no_generator(_Config) ->
513    [<<"abc">>] = [<<(id(<<"abc">>)) || true >>],
514    {<<>>} = {<<(id(<<"abc">>)) || false >>},
515
516    %% Would crash the compiler when compiled with +no_type_opt.
517    {'EXIT',{badarg,_}} = (catch << (catch "\001") || true >>),
518
519    ok.
520
521zero_pattern(Config) ->
522    case is_atom(Config) of
523        true ->
524            %% Patterns that match zero bits loops forever, so we must
525            %% be careful not to execute them.
526            _ = << <<>> || <<>> <= <<>> >>,
527            _ = << <<42>> || <<>> <= <<42>> >>,
528            _ = <<
529                  <<>> ||
530                    <<>> <= << >>,
531                    <<3:back>> <= << >>
532                >>,
533            _ = <<
534                  <<>> ||
535                    <<>> <= <<>>,
536                    <<>> <- << <<>> || area >>
537                >>;
538        false ->
539            ok
540    end.
541
542multiple_segments(_Config) ->
543    cs_init(),
544
545    [1,2] = matched_out_size(<<4, 1:4, 4, 2:4>>),
546    [42] = matched_out_size(<<16, 42:16, 72>>),
547
548    [] = do_multiple_segments_1(<<>>),
549    [] = do_multiple_segments_1(<<1>>),
550    [] = do_multiple_segments_1(<<1,2>>),
551    [] = do_multiple_segments_1(<<1,2,3>>),
552    [1,4] = do_multiple_segments_1(<<99,0,1,1,2,3,4,4>>),
553
554    [] = do_multiple_segments_2(<<1,2>>),
555    [6] = do_multiple_segments_2(<<1,2,3>>),
556    [6,15] = do_multiple_segments_2(<<1,2,3,4,5,6,7,8>>),
557
558    cs_end(),
559    ok.
560
561matched_out_size(Gen) ->
562    Bin = cs_default(<< <<X>> || <<S,X:S>> <= Gen >>),
563    List = [X || <<S,X:S>> <= Gen],
564    Bin = list_to_binary(List),
565    List.
566
567do_multiple_segments_1(Gen) ->
568    Bin = cs_default(<< <<V>> || <<V,V>> <= Gen >>),
569    List = [V || <<V,V>> <= Gen],
570    Bin = list_to_binary(List),
571    List.
572
573do_multiple_segments_2(Gen) ->
574    Bin = cs(<< <<(A+B+C)>> || <<A,B,C>> <= Gen >>),
575    List = [A+B+C || <<A,B,C>> <= Gen],
576    Bin = list_to_binary(List),
577    List.
578
579cs_init() ->
580    erts_debug:set_internal_state(available_internal_state, true),
581    ok.
582
583cs_end() ->
584    erts_debug:set_internal_state(available_internal_state, false),
585    ok.
586
587%% Verify that the allocated size is exact (rounded up to the nearest byte).
588cs(Bin) ->
589    case ?MODULE of
590        bs_bincomp_no_opt_SUITE ->
591            ok;
592        bs_bincomp_no_ssa_opt_SUITE ->
593            ok;
594        bs_bincomp_post_opt_SUITE ->
595            ok;
596        _ ->
597            ByteSize = byte_size(Bin),
598            {refc_binary,ByteSize,{binary,ByteSize},_} =
599                erts_debug:get_internal_state({binary_info,Bin})
600    end,
601    Bin.
602
603%% Verify that the allocated size of the binary is the default size.
604cs_default(Bin) ->
605    ByteSize = byte_size(Bin),
606    {refc_binary,ByteSize,{binary,256},_} =
607	erts_debug:get_internal_state({binary_info,Bin}),
608    Bin.
609
610id(I) -> I.
611