aboutsummaryrefslogblamecommitdiffstats
path: root/erts/emulator/test/iovec_SUITE.erl
blob: 963b7e2501191aa92f7de1f76485f209ecb87dd3 (plain) (tree)





















                                                                           
                                                             


                                                                              
                                                           

                                                                 








                                                                               
                                                                
                                                              
                                                
 






                             

                                                               
                                                               
 



                                                                          


                                                                     
                                                               














                                                                          
                                                               




                                                           
                                                                        



                                                
                                                              



                                                  

                                   
      
                                                               





                                                                  
                                                                 
                                                               






















                                                                        








                                                                                   

                                                                   

                                            

       
                                   

                                                                               

                                                 

                                                                            
                          

                                                                   




                                                






                                                                



                                                                             
                             


















                                                                     
%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%%     http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%% 
%% %CopyrightEnd%
%%

-module(iovec_SUITE).

-export([all/0, suite/0, init_per_suite/1, end_per_suite/1]).

-export([integer_lists/1, binary_lists/1, empty_lists/1, empty_binary_lists/1,
         mixed_lists/1, improper_lists/1, illegal_lists/1, cons_bomb/1,
         sub_binary_lists/1, iolist_to_iovec_idempotence/1,
         iolist_to_iovec_correctness/1, unaligned_sub_binaries/1,
         direct_binary_arg/1]).

-include_lib("common_test/include/ct.hrl").

suite() ->
    [{ct_hooks,[ts_install_cth]},
     {timetrap, {minutes, 2}}].

all() ->
    [integer_lists, binary_lists, empty_lists, empty_binary_lists, mixed_lists,
     sub_binary_lists, illegal_lists, improper_lists, cons_bomb,
     iolist_to_iovec_idempotence, iolist_to_iovec_correctness,
     unaligned_sub_binaries, direct_binary_arg].

init_per_suite(Config) ->
    Config.

end_per_suite(Config) ->
    application:stop(os_mon),
    Config.

integer_lists(Config) when is_list(Config) ->
    Variations = gen_variations([I || I <- lists:seq(1, 255)]),
    equivalence_test(fun erlang:iolist_to_iovec/1, Variations).

sub_binary_lists(Config) when is_list(Config) ->
    Parent = <<0:256/unit:8, "gazurka">>,
    <<0:196/unit:8, Child/binary>> = Parent,
    equivalence_test(fun erlang:iolist_to_iovec/1, gen_variations(Child)).

binary_lists(Config) when is_list(Config) ->
    Variations = gen_variations([<<I:8>> || I <- lists:seq(1, 255)]),
    equivalence_test(fun erlang:iolist_to_iovec/1, Variations).

empty_lists(Config) when is_list(Config) ->
    Variations = gen_variations([[] || _ <- lists:seq(1, 256)]),
    equivalence_test(fun erlang:iolist_to_iovec/1, Variations),
    [] = erlang:iolist_to_iovec([]),
    ok.

empty_binary_lists(Config) when is_list(Config) ->
    Variations = gen_variations([<<>> || _ <- lists:seq(1, 8192)]),
    equivalence_test(fun erlang:iolist_to_iovec/1, Variations),
    [] = erlang:iolist_to_iovec(Variations),
    ok.

mixed_lists(Config) when is_list(Config) ->
    Variations = gen_variations([<<>>, lists:seq(1, 40), <<12, 45, 78>>]),
    equivalence_test(fun erlang:iolist_to_iovec/1, Variations).

illegal_lists(Config) when is_list(Config) ->
    BitStrs = gen_variations(["gurka", <<1:1>>, "gaffel"]),
    BadInts = gen_variations(["gurka", 890, "gaffel"]),
    Atoms = gen_variations([gurka, "gaffel"]),
    BadTails = [["test" | 0], ["gurka" | gaffel], ["gaffel" | <<1:1>>]],

    Variations =
        BitStrs ++ BadInts ++ Atoms ++ BadTails,

    illegality_test(fun erlang:iolist_to_iovec/1, Variations).

improper_lists(Config) when is_list(Config) ->
    Variations = [
        [[[[1 | <<2>>] | <<3>>] | <<4>>] | <<5>>],
        [[<<1>>, 2] | <<3, 4, 5>>],
        [1, 2, 3 | <<4, 5>>]
    ],
    equivalence_test(fun erlang:iolist_to_iovec/1, Variations).

cons_bomb(Config) when is_list(Config) ->
    IntBase = gen_variations([I || I <- lists:seq(1, 255)]),
    BinBase = gen_variations([<<I:8>> || I <- lists:seq(1, 255)]),
    MixBase = gen_variations([<<12, 45, 78>>, lists:seq(1, 255)]),

    Variations = gen_variations([IntBase, BinBase, MixBase], 16),
    equivalence_test(fun erlang:iolist_to_iovec/1, Variations).

iolist_to_iovec_idempotence(Config) when is_list(Config) ->
    IntVariations = gen_variations([I || I <- lists:seq(1, 255)]),
    BinVariations = gen_variations([<<I:8>> || I <- lists:seq(1, 255)]),
    MixVariations = gen_variations([<<12, 45, 78>>, lists:seq(1, 255)]),

    Variations = [IntVariations, BinVariations, MixVariations],
    Optimized = erlang:iolist_to_iovec(Variations),

    true = Optimized =:= erlang:iolist_to_iovec(Optimized),
    ok.

iolist_to_iovec_correctness(Config) when is_list(Config) ->
    IntVariations = gen_variations([I || I <- lists:seq(1, 255)]),
    BinVariations = gen_variations([<<I:8>> || I <- lists:seq(1, 255)]),
    MixVariations = gen_variations([<<12, 45, 78>>, lists:seq(1, 255)]),

    Variations = [IntVariations, BinVariations, MixVariations],
    Optimized = erlang:iolist_to_iovec(Variations),

    true = is_iolist_equal(Optimized, Variations),
    ok.

unaligned_sub_binaries(Config) when is_list(Config) ->
    UnalignedBins = [gen_unaligned_binary(I) || I <- lists:seq(32, 4 bsl 10, 512)],
    UnalignedVariations = gen_variations(UnalignedBins),

    Optimized = erlang:iolist_to_iovec(UnalignedVariations),

    true = is_iolist_equal(Optimized, UnalignedVariations),
    ok.

direct_binary_arg(Config) when is_list(Config) ->
    {'EXIT',{badarg, _}} = (catch erlang:iolist_to_iovec(<<1:1>>)),
    [<<1>>] = erlang:iolist_to_iovec(<<1>>),
    [] = erlang:iolist_to_iovec(<<>>),
    ok.

illegality_test(Fun, Variations) ->
    [{'EXIT',{badarg, _}} = (catch Fun(Variation)) || Variation <- Variations],
    ok.

equivalence_test(Fun, [Head | _] = Variations) ->
    %% Check that each variation is equal to the others, and that the sum of
    %% them is equal to the input.
    Comparand = Fun(Head),
    [true = is_iolist_equal(Comparand, Fun(V)) || V <- Variations],
    true = is_iolist_equal(Variations, Fun(Variations)),
    ok.

is_iolist_equal(A, B) ->
    iolist_to_binary(A) =:= iolist_to_binary(B).

gen_unaligned_binary(Size) ->
    Bin0 = << <<I>> || I <- lists:seq(1, Size) >>,
    <<0:3,Bin:Size/binary,31:5>> = id(<<0:3,Bin0/binary,31:5>>),
    Bin.

id(I) -> I.

%% Generates a bunch of lists whose contents will be equal to Base repeated a
%% few times. The lists only differ by their structure, so their reduction to
%% a simpler format should yield the same result.
gen_variations(Base) ->
    gen_variations(Base, 12).
gen_variations(Base, N) ->
    [gen_flat_list(Base, N),
     gen_nested_list(Base, N),
     gen_nasty_list(Base, N)].

gen_flat_list(Base, N) ->
    lists:flatten(gen_nested_list(Base, N)).

gen_nested_list(Base, N) ->
    [Base || _ <- lists:seq(1, N)].

gen_nasty_list(Base, N) ->
    gen_nasty_list_1(gen_nested_list(Base, N), []).
gen_nasty_list_1([], Result) ->
    Result;
gen_nasty_list_1([Head | Base], Result) when is_list(Head) ->
    gen_nasty_list_1(Base, [[Result], [gen_nasty_list_1(Head, [])]]);
gen_nasty_list_1([Head | Base], Result) ->
    gen_nasty_list_1(Base, [[Result], [Head]]).