1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2004-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 21%% 22-module(ei_decode_SUITE). 23 24-include_lib("common_test/include/ct.hrl"). 25-include("ei_decode_SUITE_data/ei_decode_test_cases.hrl"). 26 27-export([all/0, suite/0, 28 init_per_testcase/2, 29 test_ei_decode_long/1, 30 test_ei_decode_ulong/1, 31 test_ei_decode_longlong/1, 32 test_ei_decode_ulonglong/1, 33 test_ei_decode_char/1, 34 test_ei_decode_nonoptimal/1, 35 test_ei_decode_misc/1, 36 test_ei_decode_utf8_atom/1]). 37 38suite() -> [{ct_hooks,[ts_install_cth]}]. 39 40all() -> 41 [test_ei_decode_long, test_ei_decode_ulong, 42 test_ei_decode_longlong, test_ei_decode_ulonglong, 43 test_ei_decode_char, test_ei_decode_nonoptimal, 44 test_ei_decode_misc, test_ei_decode_utf8_atom]. 45 46init_per_testcase(Case, Config) -> 47 runner:init_per_testcase(?MODULE, Case, Config). 48 49%% --------------------------------------------------------------------------- 50 51% NOTE: for historical reasons we don't pach as tight as we can, 52% we only fill 27 bits in 32 bit INTEGER_EXT 53 54 55%% ######################################################################## %% 56 57test_ei_decode_long(Config) when is_list(Config) -> 58 P = runner:start(Config, ?test_ei_decode_long), 59 send_integers(P), 60 runner:recv_eot(P), 61 ok. 62 63 64%% ######################################################################## %% 65 66test_ei_decode_ulong(Config) when is_list(Config) -> 67 P = runner:start(Config, ?test_ei_decode_ulong), 68 send_integers(P), 69 runner:recv_eot(P), 70 ok. 71 72 73% (*) In practical terms, other values may fit into the ext format 74% i32 is signed 32 bit on C side 75% u32 is unsigned 32 bit on C side 76 77%% ######################################################################## %% 78 79test_ei_decode_longlong(Config) when is_list(Config) -> 80 case os:type() of 81 vxworks -> 82 {skip,"Skipped on VxWorks"}; 83 _ -> 84 P = runner:start(Config, ?test_ei_decode_longlong), 85 send_integers2(P), 86 runner:recv_eot(P), 87 ok 88 end. 89 90 91%% ######################################################################## %% 92 93test_ei_decode_ulonglong(Config) when is_list(Config) -> 94 case os:type() of 95 vxworks -> 96 {skip,"Skipped on VxWorks"}; 97 _ -> 98 P = runner:start(Config, ?test_ei_decode_ulonglong), 99 send_integers2(P), 100 runner:recv_eot(P), 101 ok 102 end. 103 104 105%% ######################################################################## %% 106%% A "character" for us is an 8 bit integer, always positive, i.e. 107%% it is unsigned. 108%% FIXME maybe the API should change to use "unsigned char" to be clear?! 109 110test_ei_decode_char(Config) when is_list(Config) -> 111 P = runner:start(Config, ?test_ei_decode_char), 112 113 send_term_as_binary(P,0), 114 send_term_as_binary(P,16#7f), 115 send_term_as_binary(P,16#ff), 116 117 send_term_as_binary(P, []), % illegal type 118 119 runner:recv_eot(P), 120 ok. 121 122 123%% ######################################################################## %% 124 125test_ei_decode_nonoptimal(Config) when is_list(Config) -> 126 P = runner:start(Config, ?test_ei_decode_nonoptimal), 127 128 send_non_optimal_pos(P), % decode_char 129 send_non_optimal(P), % decode_long 130 send_non_optimal_pos(P), % decode_ulong 131 case os:type() of 132 vxworks -> 133 ok; 134 _ -> 135 send_non_optimal(P), % decode_longlong 136 send_non_optimal_pos(P) % decode_ulonglong 137 end, 138 139 runner:recv_eot(P), 140 ok. 141 142 143send_non_optimal(P) -> 144 send_non_optimal_pos(P), 145 send_non_optimal_neg(P). 146 147send_non_optimal_pos(P) -> 148 send_raw(P, <<131,97,42>>), 149 send_raw(P, <<131,98,42:32>>), 150 send_raw(P, <<131,110,1,0,42>>), 151 send_raw(P, <<131,110,2,0,42,0>>), 152 send_raw(P, <<131,110,4,0,42,0,0,0>>), 153 send_raw(P, <<131,111,0,0,0,1,0,42>>), 154 send_raw(P, <<131,111,0,0,0,2,0,42,0>>), 155 send_raw(P, <<131,111,0,0,0,3,0,42,0,0>>), 156 send_raw(P, <<131,111,0,0,0,6,0,42,0,0,0,0,0>>), 157 ok. 158 159send_non_optimal_neg(P) -> 160 % send_raw(P, <<131,97,-42>>), 161 send_raw(P, <<131,98,-42:32>>), 162 send_raw(P, <<131,110,1,1,42>>), 163 send_raw(P, <<131,110,2,1,42,0>>), 164 send_raw(P, <<131,110,4,1,42,0,0,0>>), 165 send_raw(P, <<131,111,0,0,0,1,1,42>>), 166 send_raw(P, <<131,111,0,0,0,2,1,42,0>>), 167 send_raw(P, <<131,111,0,0,0,3,1,42,0,0>>), 168 send_raw(P, <<131,111,0,0,0,6,1,42,0,0,0,0,0>>), 169 ok. 170 171 172%% ######################################################################## %% 173 174test_ei_decode_misc(Config) when is_list(Config) -> 175 P = runner:start(Config, ?test_ei_decode_misc), 176 177 send_term_as_binary(P,0.0), 178 send_term_as_binary(P,-1.0), 179 send_term_as_binary(P,1.0), 180 181 send_term_as_binary(P,false), 182 send_term_as_binary(P,true), 183 184 send_term_as_binary(P,foo), 185 send_term_as_binary(P,''), 186 %%send_term_as_binary(P,'ÅÄÖåäö'), 187 send_latin1_atom_as_binary(P, "ÅÄÖåäö"), 188 189 send_term_as_binary(P,"foo"), 190 send_term_as_binary(P,""), 191 send_term_as_binary(P,"ÅÄÖåäö"), 192 193 send_term_as_binary(P,<<"foo">>), 194 send_term_as_binary(P,<<>>), 195 send_term_as_binary(P,<<"ÅÄÖåäö">>), 196 197 % send_term_as_binary(P,{}), 198 % send_term_as_binary(P,[]), 199 200 runner:recv_eot(P), 201 ok. 202 203%% ######################################################################## %% 204 205test_ei_decode_utf8_atom(Config) -> 206 P = runner:start(Config, ?test_ei_decode_utf8_atom), 207 208 send_latin1_atom_as_binary(P,"å"), 209 send_latin1_atom_as_binary(P,"ä"), 210 send_latin1_atom_as_binary(P,"ö"), 211 send_latin1_atom_as_binary(P,"õ"), 212 213 send_utf8_atom_as_binary(P,[1758]), 214 send_utf8_atom_as_binary(P,[1758,1758]), 215 send_utf8_atom_as_binary(P,[1758,1758,1758]), 216 send_utf8_atom_as_binary(P,[1758,1758,1758,1758]), 217 218 send_latin1_atom_as_binary(P,"a"), 219 send_latin1_atom_as_binary(P,"b"), 220 221 send_term_as_binary(P,'c'), 222 send_term_as_binary(P,'d'), 223 224 runner:recv_eot(P), 225 ok. 226 227 228%% ######################################################################## %% 229 230send_term_as_binary(Port, Term) when is_port(Port) -> 231 Port ! {self(), {command, term_to_binary(Term)}}. 232 233send_raw(Port, Bin) when is_port(Port) -> 234 Port ! {self(), {command, Bin}}. 235 236send_utf8_atom_as_binary(Port, String) -> 237 Port ! {self(), {command, term_to_binary(uc_atup(String))}}. 238 239send_latin1_atom_as_binary(Port, String) -> 240 Port ! {self(), {command, encode_latin1_atom(String)}}. 241 242send_integers(P) -> 243 send_term_as_binary(P,0), % SMALL_INTEGER_EXT smallest 244 send_term_as_binary(P,255), % SMALL_INTEGER_EXT largest 245 send_term_as_binary(P,256), % INTEGER_EXT smallest pos (*) 246 send_term_as_binary(P,-1), % INTEGER_EXT largest neg 247 248 send_term_as_binary(P, 16#07ffffff), % INTEGER_EXT old largest (28 bits) 249 send_term_as_binary(P,-16#08000000), % INTEGER_EXT old smallest 250 send_term_as_binary(P, 16#08000000), % SMALL_BIG_EXT old smallest pos(*) 251 send_term_as_binary(P,-16#08000001), % SMALL_BIG_EXT old largest neg (*) 252 253 send_term_as_binary(P, 16#7fffffff), % INTEGER_EXT new largest (32 bits) 254 send_term_as_binary(P,-16#80000000), % INTEGER_EXT new smallest (32 bis) 255 send_term_as_binary(P, 16#80000000), % SMALL_BIG_EXT new smallest pos(*) 256 send_term_as_binary(P,-16#80000001), % SMALL_BIG_EXT new largest neg (*) 257 258 case erlang:system_info({wordsize,external}) of 259 4 -> 260 send_term_as_binary(P, 16#80000000),% SMALL_BIG_EXT u32 261 send_term_as_binary(P, 16#ffffffff),% SMALL_BIG_EXT largest u32 262 263 send_term_as_binary(P, 16#7fffffffffff), % largest i48 264 send_term_as_binary(P,-16#800000000000), % smallest i48 265 send_term_as_binary(P, 16#ffffffffffff), % largest u48 266 send_term_as_binary(P, 16#7fffffffffffffff), % largest i64 267 send_term_as_binary(P,-16#8000000000000000), % smallest i64 268 send_term_as_binary(P, 16#ffffffffffffffff); % largest u64 269 8 -> 270 send_term_as_binary(P, 16#8000000000000000),% SMALL_BIG_EXT u64 271 % SMALL_BIG_EXT largest u64 272 send_term_as_binary(P, 16#ffffffffffffffff), 273 % largest i96 274 send_term_as_binary(P, 16#7fffffffffffffffffffffff), 275 % smallest i96 276 send_term_as_binary(P,-16#800000000000000000000000), 277 % largest u96 278 send_term_as_binary(P, 16#ffffffffffffffffffffffff), 279 % largest i128 280 send_term_as_binary(P, 16#7fffffffffffffffffffffffffffffff), 281 % smallest i128 282 send_term_as_binary(P,-16#80000000000000000000000000000000), 283 % largest u128 284 send_term_as_binary(P, 16#ffffffffffffffffffffffffffffffff) 285 end, 286 send_term_as_binary(P, []), % illegal type 287 ok. 288 289send_integers2(P) -> 290 send_term_as_binary(P,0), % SMALL_INTEGER_EXT smallest 291 send_term_as_binary(P,255), % SMALL_INTEGER_EXT largest 292 send_term_as_binary(P,256), % INTEGER_EXT smallest pos (*) 293 send_term_as_binary(P,-1), % INTEGER_EXT largest neg 294 295 send_term_as_binary(P, 16#07ffffff), % INTEGER_EXT old largest (28 bits) 296 send_term_as_binary(P,-16#08000000), % INTEGER_EXT old smallest 297 send_term_as_binary(P, 16#08000000), % SMALL_BIG_EXT old smallest pos(*) 298 send_term_as_binary(P,-16#08000001), % SMALL_BIG_EXT old largest neg (*) 299 300 send_term_as_binary(P, 16#7fffffff), % INTEGER_EXT new largest (32 bits) 301 send_term_as_binary(P,-16#80000000), % INTEGER_EXT new smallest 302 send_term_as_binary(P, 16#80000000), % SMALL_BIG_EXT new smallest pos(*) 303 send_term_as_binary(P,-16#80000001), % SMALL_BIG_EXT new largest neg (*) 304 305 send_term_as_binary(P, 16#ffffffff), % SMALL_BIG_EXT largest u32 306 307 send_term_as_binary(P, 16#7fffffffffff), % largest i48 308 send_term_as_binary(P,-16#800000000000), % smallest i48 309 send_term_as_binary(P, 16#ffffffffffff), % largest u48 310 send_term_as_binary(P, 16#7fffffffffffffff), % largest i64 311 send_term_as_binary(P,-16#8000000000000000), % smallest i64 312 send_term_as_binary(P, 16#ffffffffffffffff), % largest u64 313 send_term_as_binary(P, []), % illegal type 314 ok. 315 316encode_latin1_atom(String) -> 317 Len = length(String), 318 %% Use ATOM_EXT (not SMALL_*) to simulate old term_to_binary 319 TagLen = [$d, Len bsr 8, Len band 16#ff], 320 list_to_binary([131, TagLen, String]). 321 322uc_atup(ATxt) -> 323 string_to_atom(ATxt). 324 325string_to_atom(String) -> 326 Utf8List = string_to_utf8_list(String), 327 Len = length(Utf8List), 328 TagLen = case Len < 256 of 329 true -> [119, Len]; 330 false -> [118, Len bsr 8, Len band 16#ff] 331 end, 332 binary_to_term(list_to_binary([131, TagLen, Utf8List])). 333 334string_to_utf8_list([]) -> 335 []; 336string_to_utf8_list([CP|CPs]) when is_integer(CP), 337 0 =< CP, 338 CP =< 16#7F -> 339 [CP | string_to_utf8_list(CPs)]; 340string_to_utf8_list([CP|CPs]) when is_integer(CP), 341 16#80 =< CP, 342 CP =< 16#7FF -> 343 [16#C0 bor (CP bsr 6), 344 16#80 bor (16#3F band CP) | string_to_utf8_list(CPs)]; 345string_to_utf8_list([CP|CPs]) when is_integer(CP), 346 16#800 =< CP, 347 CP =< 16#FFFF -> 348 [16#E0 bor (CP bsr 12), 349 16#80 bor (16#3F band (CP bsr 6)), 350 16#80 bor (16#3F band CP) | string_to_utf8_list(CPs)]; 351string_to_utf8_list([CP|CPs]) when is_integer(CP), 352 16#10000 =< CP, 353 CP =< 16#10FFFF -> 354 [16#F0 bor (CP bsr 18), 355 16#80 bor (16#3F band (CP bsr 12)), 356 16#80 bor (16#3F band (CP bsr 6)), 357 16#80 bor (16#3F band CP) | string_to_utf8_list(CPs)]. 358