1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2001-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%% 22-module(ei_print_SUITE). 23 24-include_lib("common_test/include/ct.hrl"). 25-include("ei_print_SUITE_data/ei_print_test_cases.hrl"). 26 27-export([all/0, suite/0, 28 init_per_testcase/2, 29 atoms/1, tuples/1, lists/1, strings/1, 30 maps/1, funs/1, binaries/1, bitstrings/1, 31 integers/1]). 32 33-import(runner, [get_term/1]). 34 35%% This test suite test the ei_print() function. 36%% It uses the port program "ei_format_test". 37 38suite() -> 39 [{ct_hooks,[ts_install_cth]}]. 40 41all() -> 42 [atoms, tuples, lists, strings, maps, funs, binaries, bitstrings, integers]. 43 44init_per_testcase(Case, Config) -> 45 runner:init_per_testcase(?MODULE, Case, Config). 46 47%% Tests formatting various atoms. 48 49atoms(Config) when is_list(Config) -> 50 P = runner:start(Config, ?atoms), 51 52 {term, "''"} = get_term(P), 53 {term, "a"} = get_term(P), 54 {term, "'A'"} = get_term(P), 55 {term, "abc"} = get_term(P), 56 {term, "'Abc'"} = get_term(P), 57 {term, "ab@c"} = get_term(P), 58 {term, "'The rain in Spain stays mainly in the plains'"} = get_term(P), 59 60 {term, "a"} = get_term(P), 61 {term, "ab"} = get_term(P), 62 {term, "abc"} = get_term(P), 63 {term, "ab@c"} = get_term(P), 64 {term, "abcdefghijklmnopq"} = get_term(P), 65 66 {term, "''"} = get_term(P), 67 {term, "a"} = get_term(P), 68 {term, "'A'"} = get_term(P), 69 {term, "abc"} = get_term(P), 70 {term, "'Abc'"} = get_term(P), 71 {term, "ab@c"} = get_term(P), 72 {term, "'The rain in Spain stays mainly in the plains'"} = get_term(P), 73 74 {term, "a"} = get_term(P), 75 {term, "ab"} = get_term(P), 76 {term, "abc"} = get_term(P), 77 {term, "ab@c"} = get_term(P), 78 {term, "' abcdefghijklmnopq '"} = get_term(P), 79 80 runner:recv_eot(P), 81 ok. 82 83 84 85%% Tests formatting various tuples 86 87tuples(Config) when is_list(Config) -> 88 P = runner:start(Config, ?tuples), 89 90 {term, "{}"} = get_term(P), 91 {term, "{a}"} = get_term(P), 92 {term, "{a, b}"} = get_term(P), 93 {term, "{a, b, c}"} = get_term(P), 94 {term, "{1}"} = get_term(P), 95 {term, "{[]}"} = get_term(P), 96 {term, "{[], []}"} = get_term(P), 97 {term, "{[], a, b, c}"} = get_term(P), 98 {term, "{[], a, [], b, c}"} = get_term(P), 99 {term, "{[], a, '', b, c}"} = get_term(P), 100 101 runner:recv_eot(P), 102 ok. 103 104 105 106%% Tests formatting various lists 107 108lists(Config) when is_list(Config) -> 109 P = runner:start(Config, ?lists), 110 111 {term, "[]"} = get_term(P), 112 {term, "[a]"} = get_term(P), 113 {term, "[a, b]"} = get_term(P), 114 {term, "[a, b, c]"} = get_term(P), 115 {term, "[1]"} = get_term(P), 116 {term, "[[]]"} = get_term(P), 117 {term, "[[], []]"} = get_term(P), 118 {term, "[[], a, b, c]"} = get_term(P), 119 {term, "[[], a, [], b, c]"} = get_term(P), 120 {term, "[[], a, '', b, c]"} = get_term(P), 121 {term, "[[x, 2], [y, 3], [z, 4]]"}= get_term(P), 122 123 %% {term, "[{name, 'Madonna'}, {age, 21}, {data, [{addr, "E-street", 42}]}]"} = get_term(P), 124 %% maybe regexp instead? 125 {term, "[{pi, 3.141500}, {'cos(70)', 0.342020}]"} = get_term(P), 126 {term, "[[pi, 3.141500], ['cos(70)', 0.342020]]"} = get_term(P), 127 128 {term, "[-1]"} = get_term(P), 129 130 runner:recv_eot(P), 131 ok. 132 133strings(Config) when is_list(Config) -> 134 P = runner:start(Config, ?strings), 135 136 {term, "\"\\n\""} = get_term(P), 137 {term, "\"\\r\\n\""} = get_term(P), 138 {term, "\"a\""} = get_term(P), 139 {term, "\"A\""} = get_term(P), 140 {term, "\"0\""} = get_term(P), 141 {term, "\"9\""} = get_term(P), 142 {term, "\"The rain in Spain stays mainly in the plains\""} = get_term(P), 143 {term, "\" abcdefghijklmnopq \""} = get_term(P), 144 145 runner:recv_eot(P), 146 ok. 147 148maps(Config) -> 149 P = runner:start(Config, ?maps), 150 151 {term, "#{}"} = get_term(P), 152 {term, "#{key => value}"} = get_term(P), 153 {term, "#{key => value, another_key => {ok, 42}}"} = get_term(P), 154 155 runner:recv_eot(P), 156 ok. 157 158funs(Config) -> 159 P = runner:start(Config, ?funs), 160 161 {term, "#Fun{some_module.42.3735928559}"} = get_term(P), 162 {term, "#Fun{some_module.37.195935983}"} = get_term(P), 163 {term, "fun erlang:abs/1"} = get_term(P), 164 165 runner:recv_eot(P), 166 ok. 167 168binaries(Config) -> 169 P = runner:start(Config, ?binaries), 170 171 "#Bin<>" = send_term_get_printed(P, <<>>), 172 "#Bin<1,2,3>" = send_term_get_printed(P, <<1,2,3>>), 173 "#Bin<0,127,128,255>" = send_term_get_printed(P, <<0,127,128,255>>), 174 Bin30 = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30>>, 175 "#Bin<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30>" 176 = send_term_get_printed(P, Bin30), 177 "#Bin<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,...>" 178 = send_term_get_printed(P, <<Bin30/binary,31>>), 179 180 runner:recv_eot(P), 181 ok. 182 183bitstrings(Config) -> 184 P = runner:start(Config, ?bitstrings), 185 186 "#Bits<1:1>" = send_term_get_printed(P, <<1:1>>), 187 "#Bits<123:7>" = send_term_get_printed(P, <<123:7>>), 188 "#Bits<1,2,3:4>" = send_term_get_printed(P, <<1,2,3:4>>), 189 "#Bits<0,127,128,255,126:7>" = send_term_get_printed(P, <<0,127,128,255,-2:7>>), 190 Bits30 = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, 191 20,21,22,23,24,25,26,27,28,29,30:5>>, 192 "#Bits<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30:5>" 193 = send_term_get_printed(P, Bits30), 194 "#Bin<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,241>" 195 = send_term_get_printed(P, <<Bits30/bits,1:3>>), 196 "#Bits<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,240,...>" 197 = send_term_get_printed(P, <<Bits30/bits,1:4>>), 198 199 runner:recv_eot(P), 200 ok. 201 202integers(Config) -> 203 Port = runner:start(Config, ?integers), 204 205 test_integers(Port, -1000, 1000), 206 test_integers(Port, (1 bsl 27) - 1000, (1 bsl 27) + 1000), 207 test_integers(Port, -(1 bsl 27) - 1000, -(1 bsl 27) + 1000), 208 test_integers(Port, (1 bsl 28) - 1000, (1 bsl 28) + 1000), 209 test_integers(Port, -(1 bsl 28) - 1000, -(1 bsl 28) + 1000), 210 test_integers(Port, (1 bsl 31) - 1000, (1 bsl 31) + 1000), 211 test_integers(Port, -(1 bsl 31) - 1000, -(1 bsl 31) + 1000), 212 test_integers(Port, (1 bsl 32) - 1000, (1 bsl 32) + 1000), 213 test_integers(Port, -(1 bsl 32) - 1000, -(1 bsl 32) + 1000), 214 test_integers(Port, (1 bsl 60) - 1000, (1 bsl 60) + 1000), 215 test_integers(Port, -(1 bsl 60) - 1000, -(1 bsl 60) + 1000), 216 test_integers(Port, 16#feeddeaddeadbeef - 1000, 16#feeddeaddeadbeef + 1000), 217 test_integers(Port, -16#feeddeaddeadbeef - 1000, -16#feeddeaddeadbeef + 1000), 218 test_integers(Port, (1 bsl 64) - 1000, (1 bsl 64) + 1000), 219 test_integers(Port, 16#addfeeddeaddeadbeef - 1000, 16#addfeeddeaddeadbeef + 1000), 220 test_integers(Port, -16#addfeeddeaddeadbeef - 1000, -16#addfeeddeaddeadbeef + 1000), 221 test_integers(Port, -(1 bsl 64) - 1000, -(1 bsl 64) + 1000), 222 test_integers(Port, (1 bsl 8192) - 1000, (1 bsl 8192) + 1000), 223 test_integers(Port, -(1 bsl 8192) - 1000, -(1 bsl 8192) + 1000), 224 225 "done" = send_term_get_printed(Port, done), 226 227 runner:recv_eot(Port), 228 229 ok. 230 231test_integer(Port, Int, Print) when is_integer(Int) -> 232 Res = send_term_get_printed(Port, Int), 233 case Print of 234 true -> 235 io:format("Res: ~s~n", [Res]); 236 false -> 237 ok 238 end, 239 %% Large bignums are printed in base 16... 240 Exp = case Res of 241 "16#" ++ _ -> 242 "16#" ++ integer_to_list(Int, 16); 243 "-16#" ++ _ -> 244 "-16#" ++ integer_to_list(-1*Int, 16); 245 _ -> 246 integer_to_list(Int) 247 end, 248 case Exp =:= Res of 249 true -> 250 ok; 251 false -> 252 io:format("Exp: ~s~nRes: ~s~n", [Exp, Res]), 253 ct:fail({Exp, Res}) 254 end. 255 256test_integers(Port, FromInt, ToInt) -> 257 test_integers(Port, FromInt, ToInt, true). 258 259test_integers(_Port, FromInt, ToInt, _Print) when FromInt > ToInt -> 260 ok; 261test_integers(Port, FromInt, ToInt, Print) -> 262 ok = test_integer(Port, FromInt, Print), 263 NewFromInt = FromInt + 1, 264 test_integers(Port, NewFromInt, ToInt, NewFromInt == ToInt). 265 266 267send_term_get_printed(Port, Term) -> 268 Port ! {self(), {command, term_to_binary(Term)}}, 269 {term, String} = get_term(Port), 270 String. 271