1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2005-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-module(zlib_SUITE). 22 23-include_lib("common_test/include/ct.hrl"). 24-include_lib("common_test/include/ct_event.hrl"). 25 26-export([suite/0, all/0, groups/0]). 27 28%% API group 29-export([api_open_close/1]). 30-export([api_deflateInit/1, api_deflateSetDictionary/1, api_deflateReset/1, 31 api_deflateParams/1, api_deflate/1, api_deflateEnd/1]). 32-export([api_inflateInit/1, api_inflateReset/1, api_inflate2/1, api_inflate3/1, 33 api_inflateChunk/1, api_safeInflate/1, api_inflateEnd/1]). 34-export([api_inflateSetDictionary/1, api_inflateGetDictionary/1]). 35-export([api_crc32/1, api_adler32/1]). 36-export([api_un_compress/1, api_un_zip/1, api_g_un_zip/1]). 37 38%% Examples group 39-export([intro/1]). 40 41%% Usage group 42-export([zip_usage/1, gz_usage/1, gz_usage2/1, compress_usage/1, 43 dictionary_usage/1, large_deflate/1, crc/1, adler/1, 44 only_allow_owner/1, sub_heap_binaries/1]). 45 46%% Bench group 47-export([inflate_bench_zeroed/1, inflate_bench_rand/1, 48 deflate_bench_zeroed/1, deflate_bench_rand/1, 49 chunk_bench_zeroed/1, chunk_bench_rand/1]). 50 51%% Others 52-export([smp/1, otp_9981/1, otp_7359/1]). 53 54-define(m(Guard, Expression), 55 fun() -> 56 Actual = (catch (Expression)), 57 case Actual of 58 Guard -> Actual; 59 _Other -> 60 ct:fail("Failed to match ~p, actual result was ~p", 61 [??Guard, Actual]) 62 end 63 end()). 64 65-define(EXIT(Reason), {'EXIT',{Reason,[{_,_,_,_}|_]}}). 66 67suite() -> 68 [{ct_hooks,[ts_install_cth]}, 69 {timetrap,{minutes,1}}]. 70 71all() -> 72 [{group, api}, {group, examples}, {group, func}, 73 {group, bench}, smp, 74 otp_9981, 75 otp_7359]. 76 77groups() -> 78 [{api, [], 79 [api_open_close, api_deflateInit, 80 api_deflateSetDictionary, api_deflateReset, 81 api_deflateParams, api_deflate, api_deflateEnd, 82 api_inflateInit, api_inflateSetDictionary, api_inflateGetDictionary, 83 api_inflateReset, api_inflate2, api_inflate3, api_inflateChunk, 84 api_safeInflate, api_inflateEnd, api_crc32, 85 api_adler32, api_un_compress, api_un_zip, 86 api_g_un_zip]}, 87 {examples, [], [intro]}, 88 {func, [], 89 [zip_usage, gz_usage, gz_usage2, compress_usage, 90 dictionary_usage, large_deflate, crc, adler, 91 only_allow_owner, sub_heap_binaries]}, 92 {bench, 93 [inflate_bench_zeroed, inflate_bench_rand, 94 deflate_bench_zeroed, deflate_bench_rand, 95 chunk_bench_zeroed, chunk_bench_rand]}]. 96 97%% Test open/0 and close/1. 98api_open_close(Config) when is_list(Config) -> 99 Fd1 = zlib:open(), 100 Fd2 = zlib:open(), 101 ?m(false,Fd1 == Fd2), 102 ?m(ok,zlib:close(Fd1)), 103 ?m(?EXIT(not_initialized), zlib:close(Fd1)), 104 ?m(ok,zlib:close(Fd2)), 105 106 %% Make sure that we don't get any EXIT messages if trap_exit is enabled. 107 process_flag(trap_exit, true), 108 Fd3 = zlib:open(), 109 ?m(ok,zlib:close(Fd3)), 110 receive 111 Any -> ct:fail({unexpected_message,Any}) 112 after 10 -> ok 113 end. 114 115%% Test deflateInit/2 and /6. 116api_deflateInit(Config) when is_list(Config) -> 117 Z1 = zlib:open(), 118 119 ?m(?EXIT(badarg), zlib:deflateInit(gurka, none)), 120 121 ?m(?EXIT(bad_compression_level), zlib:deflateInit(gurka, gurka)), 122 ?m(?EXIT(bad_compression_level), zlib:deflateInit(Z1, gurka)), 123 Levels = [none, default, best_speed, best_compression] ++ lists:seq(0,9), 124 lists:foreach(fun(Level) -> 125 Z = zlib:open(), 126 ?m(ok, zlib:deflateInit(Z, Level)), 127 ?m(ok,zlib:close(Z)) 128 end, Levels), 129 %% /6 130 ?m(?EXIT(bad_compression_level), 131 zlib:deflateInit(Z1,gurka,deflated,-15,8,default)), 132 133 ?m(?EXIT(bad_compression_method), 134 zlib:deflateInit(Z1,default,undefined,-15,8,default)), 135 136 ?m(?EXIT(bad_compression_strategy), 137 zlib:deflateInit(Z1,default,deflated,-15,8,0)), 138 ?m(?EXIT(bad_compression_strategy), 139 zlib:deflateInit(Z1,default,deflated,-15,8,undefined)), 140 141 ?m(?EXIT(bad_windowbits), 142 zlib:deflateInit(Z1,default,deflated,48,8,default)), 143 ?m(?EXIT(bad_windowbits), 144 zlib:deflateInit(Z1,default,deflated,-20,8,default)), 145 ?m(?EXIT(bad_windowbits), 146 zlib:deflateInit(Z1,default,deflated,-7,8,default)), 147 ?m(?EXIT(bad_windowbits), 148 zlib:deflateInit(Z1,default,deflated,7,8,default)), 149 150 ?m(?EXIT(bad_memlevel), 151 zlib:deflateInit(Z1,default,deflated,-15,0,default)), 152 ?m(?EXIT(bad_memlevel), 153 zlib:deflateInit(Z1,default,deflated,-15,10,default)), 154 155 lists:foreach(fun(Level) -> 156 Z = zlib:open(), 157 ?m(ok, zlib:deflateInit(Z, Level, deflated, -15, 8, default)), 158 ?m(ok,zlib:close(Z)) 159 end, Levels), 160 161 lists:foreach(fun(Wbits) -> 162 Z11 = zlib:open(), 163 ?m(ok, zlib:deflateInit(Z11,best_compression,deflated, 164 Wbits,8,default)), 165 Z12 = zlib:open(), 166 ?m(ok, zlib:deflateInit(Z12,default,deflated,-Wbits,8,default)), 167 ?m(ok,zlib:close(Z11)), 168 ?m(ok,zlib:close(Z12)) 169 end, lists:seq(9, 15)), 170 171 lists:foreach(fun(MemLevel) -> 172 Z = zlib:open(), 173 ?m(ok, zlib:deflateInit(Z,default,deflated,-15, 174 MemLevel,default)), 175 ?m(ok,zlib:close(Z)) 176 end, lists:seq(1,8)), 177 178 Strategies = [filtered,huffman_only,rle,default], 179 lists:foreach(fun(Strategy) -> 180 Z = zlib:open(), 181 ?m(ok, zlib:deflateInit(Z,best_speed,deflated,-15,8,Strategy)), 182 ?m(ok,zlib:close(Z)) 183 end, Strategies), 184 ?m(ok, zlib:deflateInit(Z1,default,deflated,-15,8,default)), 185 186 %% Let it crash for any reason; we don't care about the order in which the 187 %% parameters are checked. 188 ?m(?EXIT(_), zlib:deflateInit(Z1,none,deflated,-15,8,default)), 189 190 ?m(ok, zlib:close(Z1)). 191 192%% Test deflateSetDictionary. 193api_deflateSetDictionary(Config) when is_list(Config) -> 194 Z1 = zlib:open(), 195 ?m(ok, zlib:deflateInit(Z1, default)), 196 ?m(Id when is_integer(Id), zlib:deflateSetDictionary(Z1, <<1,1,2,3,4,5,1>>)), 197 ?m(Id when is_integer(Id), zlib:deflateSetDictionary(Z1, [1,1,2,3,4,5,1])), 198 ?m(?EXIT(badarg), zlib:deflateSetDictionary(Z1, gurka)), 199 ?m(?EXIT(badarg), zlib:deflateSetDictionary(Z1, 128)), 200 ?m(L when is_list(L), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)), 201 ?m(?EXIT(stream_error), zlib:deflateSetDictionary(Z1,<<1,1,2,3,4,5,1>>)), 202 ?m(ok, zlib:close(Z1)). 203 204%% Test deflateReset. 205api_deflateReset(Config) when is_list(Config) -> 206 Z1 = zlib:open(), 207 ?m(ok, zlib:deflateInit(Z1, default)), 208 ?m(L when is_list(L), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)), 209 ?m(ok, zlib:deflateReset(Z1)), 210 ?m(ok, zlib:deflateReset(Z1)), 211 %% FIXME how do I make this go wrong?? 212 ?m(ok, zlib:close(Z1)). 213 214%% Test deflateParams. 215api_deflateParams(Config) when is_list(Config) -> 216 Levels = [none, default, best_speed, best_compression] ++ lists:seq(0, 9), 217 Strategies = [filtered, huffman_only, rle, default], 218 219 Z1 = zlib:open(), 220 ?m(ok, zlib:deflateInit(Z1, default)), 221 222 ApiTest = 223 fun(Level, Strategy) -> 224 ?m(ok, zlib:deflateParams(Z1, Level, Strategy)), 225 ?m(ok, zlib:deflateReset(Z1)) 226 end, 227 228 [ ApiTest(Level, Strategy) || Level <- Levels, Strategy <- Strategies ], 229 230 ?m(ok, zlib:close(Z1)), 231 232 FlushTest = 233 fun FlushTest(Size, Level, Strategy) -> 234 Z = zlib:open(), 235 ok = zlib:deflateInit(Z, default), 236 Data = gen_determ_rand_bytes(Size), 237 case zlib:deflate(Z, Data, none) of 238 [<<120, 156>>] -> 239 %% All data is present in the internal zlib state, and will 240 %% be flushed on deflateParams. 241 242 ok = zlib:deflateParams(Z, Level, Strategy), 243 Compressed = [<<120, 156>>, zlib:deflate(Z, <<>>, finish)], 244 Data = zlib:uncompress(Compressed), 245 zlib:close(Z), 246 247 FlushTest(Size + (1 bsl 10), Level, Strategy); 248 _Other -> 249 ok 250 end 251 end, 252 253 [ FlushTest(1, Level, Strategy) || Level <- Levels, Strategy <- Strategies ], 254 255 ok. 256 257%% Test deflate. 258api_deflate(Config) when is_list(Config) -> 259 Z1 = zlib:open(), 260 ?m(ok, zlib:deflateInit(Z1, default)), 261 ?m([B] when is_binary(B), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, finish)), 262 ?m(ok, zlib:deflateReset(Z1)), 263 ?m([B] when is_binary(B), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, finish)), 264 ?m(ok, zlib:deflateReset(Z1)), 265 ?m(B when is_list(B), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>)), 266 ?m(B when is_list(B), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, none)), 267 ?m(B when is_list(B), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, sync)), 268 ?m(B when is_list(B), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, full)), 269 ?m(B when is_list(B), zlib:deflate(Z1, <<>>, finish)), 270 271 ?m(?EXIT(badarg), zlib:deflate(gurka, <<1,1,1,1,1,1,1,1,1>>, full)), 272 273 ?m(?EXIT(bad_flush_mode), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, asdj)), 274 ?m(?EXIT(bad_flush_mode), zlib:deflate(Z1, <<1,1,1,1,1,1,1,1,1>>, 198)), 275 276 %% Causes problems ERROR REPORT 277 ?m(?EXIT(badarg), zlib:deflate(Z1, [asdj,asd], none)), 278 279 ?m(ok, zlib:close(Z1)). 280 281%% Test deflateEnd. 282api_deflateEnd(Config) when is_list(Config) -> 283 Z1 = zlib:open(), 284 ?m(ok, zlib:deflateInit(Z1, default)), 285 ?m(ok, zlib:deflateEnd(Z1)), 286 ?m(?EXIT(not_initialized), zlib:deflateEnd(Z1)), 287 ?m(?EXIT(badarg), zlib:deflateEnd(gurka)), 288 ?m(ok, zlib:deflateInit(Z1, default)), 289 ?m(B when is_list(B), zlib:deflate(Z1, <<"Kilroy was here">>)), 290 ?m(?EXIT(data_error), zlib:deflateEnd(Z1)), 291 ?m(ok, zlib:deflateInit(Z1, default)), 292 ?m(B when is_list(B), zlib:deflate(Z1, <<"Kilroy was here">>)), 293 ?m(B when is_list(B), zlib:deflate(Z1, <<"Kilroy was here">>, finish)), 294 ?m(ok, zlib:deflateEnd(Z1)), 295 296 ?m(ok, zlib:close(Z1)). 297 298%% Test inflateInit /1 and /2. 299api_inflateInit(Config) when is_list(Config) -> 300 Z1 = zlib:open(), 301 ?m(?EXIT(badarg), zlib:inflateInit(gurka)), 302 ?m(ok, zlib:inflateInit(Z1)), 303 ?m(?EXIT(already_initialized), zlib:inflateInit(Z1, 15)), 304 lists:foreach(fun(Wbits) -> 305 Z11 = zlib:open(), 306 ?m(ok, zlib:inflateInit(Z11,Wbits)), 307 Z12 = zlib:open(), 308 ?m(ok, zlib:inflateInit(Z12,-Wbits)), 309 ?m(ok,zlib:close(Z11)), 310 ?m(ok,zlib:close(Z12)) 311 end, lists:seq(8,15)), 312 ?m(?EXIT(badarg), zlib:inflateInit(gurka, -15)), 313 ?m(?EXIT(bad_windowbits), zlib:inflateInit(Z1, 7)), 314 ?m(?EXIT(bad_windowbits), zlib:inflateInit(Z1, -7)), 315 ?m(?EXIT(bad_windowbits), zlib:inflateInit(Z1, 48)), 316 ?m(?EXIT(bad_windowbits), zlib:inflateInit(Z1, -16)), 317 ?m(ok, zlib:close(Z1)). 318 319%% Test inflateSetDictionary. 320api_inflateSetDictionary(Config) when is_list(Config) -> 321 Z1 = zlib:open(), 322 ?m(ok, zlib:inflateInit(Z1)), 323 ?m(?EXIT(badarg), zlib:inflateSetDictionary(gurka,<<1,1,1,1,1>>)), 324 ?m(?EXIT(badarg), zlib:inflateSetDictionary(Z1,102)), 325 ?m(?EXIT(badarg), zlib:inflateSetDictionary(Z1,gurka)), 326 Dict = <<1,1,1,1,1>>, 327 ?m(?EXIT(stream_error), zlib:inflateSetDictionary(Z1,Dict)), 328 ?m(ok, zlib:close(Z1)). 329 330%% Test inflateGetDictionary. 331api_inflateGetDictionary(Config) when is_list(Config) -> 332 Z1 = zlib:open(), 333 zlib:inflateInit(Z1), 334 IsOperationSupported = 335 case catch zlib:inflateGetDictionary(Z1) of 336 ?EXIT(not_supported) -> false; 337 _ -> true 338 end, 339 zlib:close(Z1), 340 api_inflateGetDictionary_if_supported(IsOperationSupported). 341 342api_inflateGetDictionary_if_supported(false) -> 343 {skip, "inflateGetDictionary/1 unsupported in current setup"}; 344api_inflateGetDictionary_if_supported(true) -> 345 % Compress payload using custom dictionary 346 Z1 = zlib:open(), 347 ?m(ok, zlib:deflateInit(Z1)), 348 Dict = <<"foobar barfoo foo bar far boo">>, 349 Checksum = zlib:deflateSetDictionary(Z1, Dict), 350 Payload = <<"foobarbarbar">>, 351 Compressed = zlib:deflate(Z1, Payload, finish), 352 ?m(ok, zlib:close(Z1)), 353 354 % Decompress and test dictionary extraction with inflate/2 355 Z2 = zlib:open(), 356 ?m(ok, zlib:inflateInit(Z2)), 357 ?m(<<>>, iolist_to_binary(zlib:inflateGetDictionary(Z2))), 358 ?m(?EXIT(stream_error), zlib:inflateSetDictionary(Z2, Dict)), 359 ?m(?EXIT({need_dictionary,Checksum}), zlib:inflate(Z2, Compressed)), 360 ?m(ok, zlib:inflateSetDictionary(Z2, Dict)), 361 ?m(Dict, iolist_to_binary(zlib:inflateGetDictionary(Z2))), 362 Payload = iolist_to_binary(zlib:inflate(Z2, [])), 363 ?m(ok, zlib:close(Z2)), 364 ?m(?EXIT(not_initialized), zlib:inflateSetDictionary(Z2, Dict)), 365 366 %% ... And do the same for inflate/3 367 Z3 = zlib:open(), 368 ?m(ok, zlib:inflateInit(Z3)), 369 ?m(<<>>, iolist_to_binary(zlib:inflateGetDictionary(Z3))), 370 ?m(?EXIT(stream_error), zlib:inflateSetDictionary(Z3, Dict)), 371 372 {need_dictionary, Checksum, _Output = []} = 373 zlib:inflate(Z3, Compressed, [{exception_on_need_dict, false}]), 374 375 ?m(ok, zlib:inflateSetDictionary(Z3, Dict)), 376 ?m(Dict, iolist_to_binary(zlib:inflateGetDictionary(Z3))), 377 378 Payload = iolist_to_binary( 379 zlib:inflate(Z3, [], [{exception_on_need_dict, false}])), 380 381 ?m(ok, zlib:close(Z3)), 382 ?m(?EXIT(not_initialized), zlib:inflateSetDictionary(Z3, Dict)), 383 384 ok. 385 386%% Test inflateReset. 387api_inflateReset(Config) when is_list(Config) -> 388 Z1 = zlib:open(), 389 ?m(ok, zlib:inflateInit(Z1)), 390 ?m(?EXIT(badarg), zlib:inflateReset(gurka)), 391 ?m(ok, zlib:inflateReset(Z1)), 392 ?m(ok, zlib:close(Z1)). 393 394%% Test inflate/2 395api_inflate2(Config) when is_list(Config) -> 396 Data = [<<1,2,2,3,3,3,4,4,4,4>>], 397 Compressed = zlib:compress(Data), 398 399 Z1 = zlib:open(), 400 ?m(ok, zlib:inflateInit(Z1)), 401 ?m([], zlib:inflate(Z1, <<>>)), 402 ?m(Data, zlib:inflate(Z1, Compressed)), 403 ?m(ok, zlib:inflateEnd(Z1)), 404 ?m(ok, zlib:inflateInit(Z1)), 405 ?m(Data, zlib:inflate(Z1, Compressed)), 406 ?m(?EXIT(badarg), zlib:inflate(gurka, Compressed)), 407 ?m(?EXIT(badarg), zlib:inflate(Z1, 4384)), 408 ?m(?EXIT(badarg), zlib:inflate(Z1, [atom_list])), 409 ?m(ok, zlib:inflateEnd(Z1)), 410 ?m(ok, zlib:inflateInit(Z1)), 411 ?m(?EXIT(data_error), zlib:inflate(Z1, <<2,1,2,1,2>>)), 412 ?m(ok, zlib:close(Z1)), 413 414 %% OTP-17299: we failed to fully flush the zlib state if we ran out of 415 %% input and filled the internal output buffer at the same time. 416 EdgeCaseData = <<"gurka", 0:16384/integer-unit:8>>, 417 EdgeCaseZipped = zlib:zip(EdgeCaseData), 418 Z2 = zlib:open(), 419 ?m(ok, zlib:inflateInit(Z2, -15)), 420 Unzipped = iolist_to_binary(zlib:inflate(Z2, EdgeCaseZipped)), 421 ?m(EdgeCaseData, Unzipped), 422 ?m(ok, zlib:inflateEnd(Z2)), 423 ?m(ok, zlib:close(Z2)), 424 425 ok. 426 427%% Test inflate/3; same as inflate/2 but with the default options inverted. 428api_inflate3(Config) when is_list(Config) -> 429 Data = [<<1,2,2,3,3,3,4,4,4,4>>], 430 Options = [{exception_on_need_dict, false}], 431 Compressed = zlib:compress(Data), 432 Z1 = zlib:open(), 433 ?m(ok, zlib:inflateInit(Z1)), 434 ?m([], zlib:inflate(Z1, <<>>, Options)), 435 ?m(Data, zlib:inflate(Z1, Compressed)), 436 ?m(ok, zlib:inflateEnd(Z1)), 437 ?m(ok, zlib:inflateInit(Z1)), 438 ?m(Data, zlib:inflate(Z1, Compressed, Options)), 439 ?m(?EXIT(badarg), zlib:inflate(gurka, Compressed, Options)), 440 ?m(?EXIT(badarg), zlib:inflate(Z1, 4384, Options)), 441 ?m(?EXIT(badarg), zlib:inflate(Z1, [atom_list], Options)), 442 ?m(ok, zlib:inflateEnd(Z1)), 443 ?m(ok, zlib:inflateInit(Z1)), 444 ?m(?EXIT(data_error), zlib:inflate(Z1, <<2,1,2,1,2>>, Options)), 445 ?m(ok, zlib:close(Z1)). 446 447%% Test inflateChunk. 448api_inflateChunk(Config) when is_list(Config) -> 449 ChunkSize = 1024, 450 Data = << <<(I rem 150)>> || I <- lists:seq(1, 3 * ChunkSize) >>, 451 Part1 = binary:part(Data, 0, ChunkSize), 452 Part2 = binary:part(Data, ChunkSize, ChunkSize), 453 Part3 = binary:part(Data, ChunkSize * 2, ChunkSize), 454 455 Compressed = zlib:compress(Data), 456 Z1 = zlib:open(), 457 458 zlib:setBufSize(Z1, ChunkSize), 459 460 ?m(ok, zlib:inflateInit(Z1)), 461 462 0 = iolist_size(zlib:inflateChunk(Z1, <<>>)), 463 464 {more, Part1AsIOList} = zlib:inflateChunk(Z1, Compressed), 465 {more, Part2AsIOList} = zlib:inflateChunk(Z1), 466 {more, Part3AsIOList} = zlib:inflateChunk(Z1), 467 468 [] = zlib:inflateChunk(Z1), 469 [] = zlib:inflateChunk(Z1), 470 [] = zlib:inflateChunk(Z1), 471 472 ?m(Part1, iolist_to_binary(Part1AsIOList)), 473 ?m(Part2, iolist_to_binary(Part2AsIOList)), 474 ?m(Part3, iolist_to_binary(Part3AsIOList)), 475 476 ?m(ok, zlib:inflateEnd(Z1)), 477 ?m(ok, zlib:inflateInit(Z1)), 478 479 ?m({more, Part1AsIOList}, zlib:inflateChunk(Z1, Compressed)), 480 481 ?m(ok, zlib:inflateReset(Z1)), 482 483 zlib:setBufSize(Z1, byte_size(Data) + 1), 484 485 DataAsIOList = zlib:inflateChunk(Z1, Compressed), 486 ?m(Data, iolist_to_binary(DataAsIOList)), 487 488 ?m(ok, zlib:inflateEnd(Z1)), 489 ?m(ok, zlib:inflateInit(Z1)), 490 491 ?m(?EXIT(badarg), zlib:inflateChunk(gurka, Compressed)), 492 ?m(?EXIT(badarg), zlib:inflateChunk(Z1, 4384)), 493 494 ?m(?EXIT(data_error), zlib:inflateEnd(Z1)), 495 496 ?m(ok, zlib:close(Z1)). 497 498%% Test safeInflate as a mirror of inflateChunk, but ignore the stuff about 499%% exact chunk sizes. 500api_safeInflate(Config) when is_list(Config) -> 501 Data = << <<(I rem 150)>> || I <- lists:seq(1, 20 bsl 10) >>, 502 Compressed = zlib:compress(Data), 503 Z1 = zlib:open(), 504 505 ?m(ok, zlib:inflateInit(Z1)), 506 507 SafeInflateLoop = 508 fun 509 Loop({continue, Chunk}, Output) -> 510 Loop(zlib:safeInflate(Z1, []), [Output, Chunk]); 511 Loop({finished, Chunk}, Output) -> 512 [Output, Chunk] 513 end, 514 515 Decompressed = SafeInflateLoop(zlib:safeInflate(Z1, Compressed), []), 516 Data = iolist_to_binary(Decompressed), 517 518 ?m(ok, zlib:inflateEnd(Z1)), 519 ?m(ok, zlib:inflateInit(Z1)), 520 521 {continue, Partial} = zlib:safeInflate(Z1, Compressed), 522 PBin = iolist_to_binary(Partial), 523 PSize = byte_size(PBin), 524 <<PBin:PSize/binary, Rest/binary>> = Data, 525 526 ?m(ok, zlib:inflateReset(Z1)), 527 528 {continue, Partial} = zlib:safeInflate(Z1, Compressed), 529 PBin = iolist_to_binary(Partial), 530 PSize = byte_size(PBin), 531 <<PBin:PSize/binary, Rest/binary>> = Data, 532 533 ?m(ok, zlib:inflateReset(Z1)), 534 535 SafeInflateLoop(zlib:safeInflate(Z1, Compressed), []), 536 537 ?m({finished, []}, zlib:safeInflate(Z1, Compressed)), 538 ?m({finished, []}, zlib:safeInflate(Z1, Compressed)), 539 540 ?m(ok, zlib:inflateReset(Z1)), 541 ?m(?EXIT(badarg), zlib:safeInflate(gurka, Compressed)), 542 ?m(?EXIT(badarg), zlib:safeInflate(Z1, 4384)), 543 ?m(?EXIT(data_error), zlib:inflateEnd(Z1)), 544 ?m(ok, zlib:close(Z1)). 545 546%% Test inflateEnd. 547api_inflateEnd(Config) when is_list(Config) -> 548 Z1 = zlib:open(), 549 ?m(?EXIT(not_initialized), zlib:inflateEnd(Z1)), 550 ?m(ok, zlib:inflateInit(Z1)), 551 ?m(?EXIT(badarg), zlib:inflateEnd(gurka)), 552 ?m(?EXIT(data_error), zlib:inflateEnd(Z1)), 553 ?m(?EXIT(not_initialized), zlib:inflateEnd(Z1)), 554 ?m(ok, zlib:inflateInit(Z1)), 555 ?m(B when is_list(B), zlib:inflate(Z1, zlib:compress("abc"))), 556 ?m(ok, zlib:inflateEnd(Z1)), 557 ?m(ok, zlib:close(Z1)). 558 559%% Test crc32. 560api_crc32(Config) when is_list(Config) -> 561 Z1 = zlib:open(), 562 ?m(ok, zlib:deflateInit(Z1,best_speed,deflated,-15,8,default)), 563 Bin = <<1,1,1,1,1,1,1,1,1>>, 564 Compressed1 = ?m(L when is_list(L), zlib:deflate(Z1, Bin, none)), 565 Compressed2 = ?m(L when is_list(L), zlib:deflate(Z1, <<>>, finish)), 566 Compressed = list_to_binary(Compressed1 ++ Compressed2), 567 CRC1 = ?m( CRC1 when is_integer(CRC1), zlib:crc32(Z1)), 568 ?m(CRC1 when is_integer(CRC1), zlib:crc32(Z1,Bin)), 569 ?m(CRC1 when is_integer(CRC1), zlib:crc32(Z1,binary_to_list(Bin))), 570 ?m(CRC2 when is_integer(CRC2), zlib:crc32(Z1,Compressed)), 571 CRC2 = ?m(CRC2 when is_integer(CRC2), zlib:crc32(Z1,0,Compressed)), 572 ?m(CRC3 when CRC2 /= CRC3, zlib:crc32(Z1,234,Compressed)), 573 ?m(?EXIT(badarg), zlib:crc32(gurka)), 574 ?m(?EXIT(badarg), zlib:crc32(Z1, not_a_binary)), 575 ?m(?EXIT(badarg), zlib:crc32(gurka, <<1,1,2,4,4>>)), 576 ?m(?EXIT(badarg), zlib:crc32(Z1, 2298929, not_a_binary)), 577 ?m(?EXIT(badarg), zlib:crc32(Z1, not_an_int, <<123,123,123,35,231>>)), 578 ?m(?EXIT(badarg), zlib:crc32_combine(Z1, not_an_int, 123123, 123)), 579 ?m(?EXIT(badarg), zlib:crc32_combine(Z1, noint, 123123, 123)), 580 ?m(?EXIT(badarg), zlib:crc32_combine(Z1, 123123, noint, 123)), 581 ?m(?EXIT(badarg), zlib:crc32_combine(Z1, 123123, 123, noint)), 582 ?m(ok, zlib:deflateEnd(Z1)), 583 ?m(ok, zlib:close(Z1)). 584 585%% Test adler32. 586api_adler32(Config) when is_list(Config) -> 587 Z1 = zlib:open(), 588 ?m(ok, zlib:deflateInit(Z1,best_speed,deflated,-15,8,default)), 589 Bin = <<1,1,1,1,1,1,1,1,1>>, 590 Compressed1 = ?m(L when is_list(L), zlib:deflate(Z1, Bin, none)), 591 Compressed2 = ?m(L when is_list(L), zlib:deflate(Z1, <<>>, finish)), 592 Compressed = list_to_binary(Compressed1 ++ Compressed2), 593 ?m(ADLER1 when is_integer(ADLER1), zlib:adler32(Z1,Bin)), 594 ?m(ADLER1 when is_integer(ADLER1), zlib:adler32(Z1,binary_to_list(Bin))), 595 ADLER2 = ?m(ADLER2 when is_integer(ADLER2), zlib:adler32(Z1,Compressed)), 596 ?m(ADLER2 when is_integer(ADLER2), zlib:adler32(Z1,1,Compressed)), 597 ?m(ADLER3 when ADLER2 /= ADLER3, zlib:adler32(Z1,234,Compressed)), 598 ?m(?EXIT(badarg), zlib:adler32(Z1, not_a_binary)), 599 ?m(?EXIT(badarg), zlib:adler32(gurka, <<1,1,2,4,4>>)), 600 ?m(?EXIT(badarg), zlib:adler32(Z1, 2298929, not_a_binary)), 601 ?m(?EXIT(badarg), zlib:adler32(Z1, not_an_int, <<123,123,123,35,231>>)), 602 ?m(?EXIT(badarg), zlib:adler32_combine(Z1, noint, 123123, 123)), 603 ?m(?EXIT(badarg), zlib:adler32_combine(Z1, 123123, noint, 123)), 604 ?m(?EXIT(badarg), zlib:adler32_combine(Z1, 123123, 123, noint)), 605 ?m(ok, zlib:deflateEnd(Z1)), 606 ?m(ok, zlib:close(Z1)). 607 608%% Test compress. 609api_un_compress(Config) when is_list(Config) -> 610 ?m(?EXIT(badarg),zlib:compress(not_a_binary)), 611 Bin = <<1,11,1,23,45>>, 612 Comp = zlib:compress(Bin), 613 ?m(?EXIT(badarg),zlib:uncompress(not_a_binary)), 614 ?m(?EXIT(data_error), zlib:uncompress(<<171,171,171,171,171>>)), 615 ?m(?EXIT(data_error), zlib:uncompress(<<>>)), 616 ?m(?EXIT(data_error), zlib:uncompress(<<120>>)), 617 ?m(?EXIT(data_error), zlib:uncompress(<<120,156>>)), 618 ?m(?EXIT(data_error), zlib:uncompress(<<120,156,3>>)), 619 ?m(?EXIT(data_error), zlib:uncompress(<<120,156,3,0>>)), 620 ?m(?EXIT(data_error), zlib:uncompress(<<0,156,3,0,0,0,0,1>>)), 621 ?m(Bin, zlib:uncompress(binary_to_list(Comp))), 622 ?m(Bin, zlib:uncompress(Comp)). 623 624%% Test zip. 625api_un_zip(Config) when is_list(Config) -> 626 ?m(?EXIT(badarg),zlib:zip(not_a_binary)), 627 Bin = <<1,11,1,23,45>>, 628 Comp = zlib:zip(Bin), 629 ?m(Comp, zlib:zip(binary_to_list(Bin))), 630 ?m(?EXIT(badarg),zlib:unzip(not_a_binary)), 631 ?m(?EXIT(data_error), zlib:unzip(<<171,171,171,171,171>>)), 632 ?m(?EXIT(data_error), zlib:unzip(<<>>)), 633 ?m(Bin, zlib:unzip(Comp)), 634 ?m(Bin, zlib:unzip(binary_to_list(Comp))), 635 636 %% OTP-6396 637 B = 638 <<131,104,19,100,0,13,99,95,99,105,100,95,99,115,103,115,110,95,50,97, 639 1,107,0,4,208,161,246,29,107,0,3,237,166,224,107,0,6,66,240,153,0,2, 640 10,1,0,8,97,116,116,97,99,104,101,100,104,2,100,0,22,117,112,100,97, 641 116,101,95,112,100,112,95,99,111,110,116,101,120,116,95,114,101,113, 642 107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104,12,3,197, 643 31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64,104,116,73, 644 64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,5,0,33,4,4,10 645 ,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,1,114,45,97, 646 112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99,50,52,48,4, 647 103,112,114,115,8,0,104,2,104,2,100,0,8,97,99,116,105,118,97,116,101, 648 104,23,100,0,11,112,100,112,95,99,111,110,116,1,120,116,100,0,7,112, 649 114,105,109,97,114,121,97,1,100,0,9,117,110,100,101,102,105,110,101, 650 100,97,1,97,4,97,4,97,7,100,0,9,117,110,100,101,102,105,110,101,100, 651 100,0,9,117,110,100,101,102,105,110,10100,100,0,9,117,110,100,101, 652 102,105,110,101,100,100,0,5,102,97,108,115,101,100,0,9,117,110,100, 653 101,102,105,110,101,100,100,0,9,117,110,100,101,102,105,110,101,100, 654 100,0,9,117,110,100,101,102,105,1,101,100,97,0,100,0,9,117,110,100, 655 101,102,105,110,101,100,107,0,4,16,0,1,144,107,0,4,61,139,186,181, 656 107,0,4,10,8,201,49,100,0,9,117,110,100,101,102,105,110,101,100,100, 657 0,9,117,110,100,101,102,105,0,101,100,100,0,9,117,110,100,101,102, 658 105,110,101,100,104,2,104,3,98,0,0,7,214,97,11,97,20,104,3,97,17,97, 659 16,97,21,106,108,0,0,0,3,104,2,97,1,104,2,104,3,98,0,0,7,214,97,11, 660 97,20,104,3,97,17,97,167,20,104,2,97,4,104,2,104,3,98,0,0,7,214,97, 661 11,97,20,104,3,97,17,97,16,97,21,104,2,97,10,104,2,104,3,98,0,0,7, 662 214,97,11,97,20,104,3,97,17,97,16,97,26,106,100,0,5,118,101,114,57, 663 57,100,0,9,117,110,0,101,102,105,110,101,100,107,0,2,0,244,107,0,4, 664 10,6,102,195,107,0,4,10,6,102,195,100,0,9,117,110,100,101,102,105, 665 110,101,100,100,0,9,117,110,100,101,102,105,110,101,100,107,0,125, 666 248,143,0,203,25115,157,116,65,185,65,172,55,87,164,88,225,50,203, 667 251,115,157,116,65,185,65,172,55,87,164,88,225,50,0,0,82,153,50,0, 668 200,98,87,148,237,193,185,65,149,167,69,144,14,16,153,50,3,81,70,94, 669 13,109,193,1,120,5,181,113,198,118,50,3,81,70,94,13,109,193,185,120, 670 5,181,113,198,118,153,3,81,70,94,13,109,193,185,120,5,181,113,198, 671 118,153,50,16,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,113,92,2,119,128,0,0, 672 108,0,0,1,107,0,114,69,3,12,1,11,97,31,113,150,64,104,132,61,64,104, 673 12,3,11,97,31,113,150,64,104,132,61,64,104,12,1,11,97,31,115,150,64, 674 104,116,73,64,104,0,0,0,0,0,0,65,149,16,61,65,149,16,61,1,241,33,4,0, 675 33,4,4,10,6,10,181,4,10,6,10,181,38,15,99,111,109,109,97,110,100,101, 676 114,45,97,112,110,45,49,3,99,111,109,5,109,110,99,57,57,6,109,99,99, 677 50,52,48,4,103,112,114,115,8,0,106>>, 678 679 Z = zlib:zip(B), 680 ?m(B, zlib:unzip(Z)). 681 682%% Test gunzip. 683api_g_un_zip(Config) when is_list(Config) -> 684 ?m(?EXIT(badarg),zlib:gzip(not_a_binary)), 685 Bin = <<1,11,1,23,45>>, 686 Comp = zlib:gzip(Bin), 687 688 ?m(Comp, zlib:gzip(binary_to_list(Bin))), 689 ?m(?EXIT(badarg), zlib:gunzip(not_a_binary)), 690 ?m(?EXIT(data_error), zlib:gunzip(<<171,171,171,171,171>>)), 691 ?m(?EXIT(data_error), zlib:gunzip(<<>>)), 692 ?m(Bin, zlib:gunzip(Comp)), 693 ?m(Bin, zlib:gunzip(binary_to_list(Comp))), 694 695 %% RFC 1952: 696 %% 697 %% "A gzip file consists of a series of "members" (compressed data 698 %% sets). [...] The members simply appear one after another in the file, 699 %% with no additional information before, between, or after them." 700 Concatenated = <<Bin/binary, Bin/binary>>, 701 ?m(Concatenated, zlib:gunzip([Comp, Comp])), 702 703 %% Don't explode if the uncompressed size is a perfect multiple of the 704 %% internal inflate chunk size. 705 ChunkSizedData = <<0:16384/unit:8>>, 706 ?m(ChunkSizedData, zlib:gunzip(zlib:gzip(ChunkSizedData))), 707 708 %% Bad CRC; bad length. 709 BadCrc = bad_crc_data(), 710 ?m(?EXIT(data_error),(catch zlib:gunzip(BadCrc))), 711 BadLen = bad_len_data(), 712 ?m(?EXIT(data_error),(catch zlib:gunzip(BadLen))), 713 ok. 714 715bad_crc_data() -> 716 %% zlib:zip(<<42>>), one byte changed. 717 <<31,139,8,0,0,0,0,0,0,3,211,2,0,91,39,185,9,1,0,0,0>>. 718 719bad_len_data() -> 720 %% zlib:zip(<<42>>), one byte changed. 721 <<31,139,8,0,0,0,0,0,0,3,211,2,0,91,38,185,9,2,0,0,0>>. 722 723 724intro(Config) when is_list(Config) -> 725 D = <<"This is a binary">>, 726 [put({ex, N}, <<"This is a binary">>) || N <- [0,1,2,3,4]], 727 put({ex, 5}, end_of_data), 728 put(ex,0), 729 Read = fun() -> 730 N = get(ex), 731 put(ex,N+1), 732 get({ex,N}) 733 end, 734 735 Z = zlib:open(), 736 ok = zlib:deflateInit(Z,default), 737 738 Compress = fun(end_of_data, _Cont) -> []; 739 (Data, Cont) -> 740 [zlib:deflate(Z, Data)|Cont(Read(),Cont)] 741 end, 742 Compressed = Compress(Read(),Compress), 743 Last = zlib:deflate(Z, [], finish), 744 ok = zlib:deflateEnd(Z), 745 zlib:close(Z), 746 Res = list_to_binary([Compressed|Last]), 747 Orig = list_to_binary(lists:duplicate(5, D)), 748 ?m(Orig, zlib:uncompress(Res)). 749 750 751%% Test deflate large file, which had a bug reported on erlang-bugs. 752large_deflate(Config) when is_list(Config) -> 753 large_deflate_do(). 754large_deflate_do() -> 755 Plain = gen_determ_rand_bytes(64 bsl 10), 756 Deflated = zlib:zip(Plain), 757 ?m(Plain, zlib:unzip(Deflated)). 758 759%% Test a standard compressed zip file. 760zip_usage(Config) when is_list(Config) -> 761 zip_usage(zip_usage({get_arg,Config})); 762zip_usage({get_arg,Config}) -> 763 Out = get_data_dir(Config), 764 {ok,ZIP} = file:read_file(filename:join(Out,"zipdoc.zip")), 765 {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")), 766 {run,ZIP,ORIG}; 767zip_usage({run,ZIP,ORIG}) -> 768 <<_:14/binary, CRC:32/little, 769 CompSz:32/little, UnCompSz:32/little,_:31/binary, 770 Compressed:CompSz/binary, _/binary>> = ZIP, 771 772 %%io:format("CRC ~p CSz ~p UnCSz ~p ~n", [CRC,CompSz,UnCompSz]), 773 Split = split_bin(Compressed,[]), 774 Z = zlib:open(), 775 776 ?m(ok, zlib:inflateInit(Z, -15)), 777 Bs = [zlib:inflate(Z, Part) || Part <- Split], 778 UC0 = list_to_binary(Bs), 779 ?m(UnCompSz, byte_size(UC0)), 780 ?m(CRC, zlib:crc32(Z)), 781 ?m(true, zlib:crc32(Z,UC0) == zlib:crc32(Z,ORIG)), 782 ?m(ok, zlib:inflateEnd(Z)), 783 784 UC1 = zlib:unzip(Compressed), 785 ?m(UnCompSz, byte_size(UC1)), 786 ?m(true, zlib:crc32(Z,UC1) == zlib:crc32(Z,ORIG)), 787 788 ?m(ok, zlib:inflateInit(Z, -15)), 789 UC2 = zlib:inflate(Z, Compressed), 790 ?m(UnCompSz, byte_size(list_to_binary(UC2))), 791 ?m(CRC, zlib:crc32(Z)), 792 ?m(true, zlib:crc32(Z,UC2) == zlib:crc32(Z,ORIG)), 793 ?m(ok, zlib:inflateEnd(Z)), 794 795 ?m(ok, zlib:inflateInit(Z, -15)), 796 UC3 = zlib:inflate(Z, Split), % Test multivec. 797 ?m(UnCompSz, byte_size(list_to_binary(UC3))), 798 ?m(true, zlib:crc32(Z,UC3) == zlib:crc32(Z,ORIG)), 799 ?m(CRC, zlib:crc32(Z)), 800 ?m(ok, zlib:inflateEnd(Z)), 801 802 ?m(ok, zlib:inflateInit(Z, -15)), 803 ?m(ok, zlib:setBufSize(Z, UnCompSz *2)), 804 UC4 = zlib:inflate(Z, Compressed), 805 ?m(UnCompSz, byte_size(list_to_binary(UC4))), 806 ?m(CRC, zlib:crc32(Z)), 807 ?m(CRC, zlib:crc32(Z,UC4)), 808 ?m(true, zlib:crc32(Z,UC4) == zlib:crc32(Z,ORIG)), 809 ?m(ok, zlib:inflateEnd(Z)), 810 811 C1 = zlib:zip(ORIG), 812 UC5 = zlib:unzip(C1), 813 ?m(CRC, zlib:crc32(Z,UC5)), 814 ?m(true,zlib:crc32(Z,UC5) == zlib:crc32(Z,ORIG)), 815 816 ?m(ok, zlib:deflateInit(Z, default, deflated, -15, 8, default)), 817 C2 = zlib:deflate(Z, ORIG, finish), 818 ?m(ORIG, zlib:unzip(C2)), 819 ?m(ok, zlib:deflateEnd(Z)), 820 821 ?m(ok, zlib:deflateInit(Z, none, deflated, -15, 8, filtered)), 822 ?m(ok, zlib:deflateParams(Z, default, default)), 823 C3 = zlib:deflate(Z, ORIG, finish), 824 ?m(ORIG, zlib:unzip(C3)), 825 ?m(ok, zlib:deflateEnd(Z)), 826 827 ok = zlib:close(Z), 828 ok. 829 830%% Test a standard compressed gzipped file. 831gz_usage(Config) when is_list(Config) -> 832 gz_usage(gz_usage({get_arg,Config})); 833gz_usage({get_arg,Config}) -> 834 Out = get_data_dir(Config), 835 {ok,GZIP} = file:read_file(filename:join(Out,"zipdoc.1.gz")), 836 {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")), 837 {ok,GZIP2} = file:read_file(filename:join(Out,"zipdoc.txt.gz")), 838 {run,GZIP,ORIG,GZIP2}; 839gz_usage({run,GZIP,ORIG,GZIP2}) -> 840 Z = zlib:open(), 841 UC1 = zlib:gunzip(GZIP), 842 ?m(true,zlib:crc32(Z,UC1) == zlib:crc32(Z,ORIG)), 843 UC3 = zlib:gunzip(GZIP2), 844 ?m(true,zlib:crc32(Z,UC3) == zlib:crc32(Z,ORIG)), 845 Compressed = zlib:gzip(ORIG), 846 UC5 = zlib:gunzip(Compressed), 847 ?m(true,zlib:crc32(Z,UC5) == zlib:crc32(Z,ORIG)), 848 ok = zlib:close(Z). 849 850%% Test more of a standard compressed gzipped file. 851gz_usage2(Config) -> 852 case os:find_executable("gzip") of 853 Name when is_list(Name) -> 854 Z = zlib:open(), 855 Out = get_data_dir(Config), 856 {ok,ORIG} = file:read_file(filename:join(Out,"zipdoc")), 857 Compressed = zlib:gzip(ORIG), 858 GzOutFile = filename:join(Out,"out.gz"), 859 OutFile = filename:join(Out,"out.txt"), 860 ?m(ok, file:write_file(GzOutFile,Compressed)), 861 os:cmd("gzip -c -d " ++ GzOutFile ++ " > " ++ OutFile), 862 case file:read_file(OutFile) of 863 {ok,ExtDecompressed} -> 864 ?m(true, 865 zlib:crc32(Z,ExtDecompressed) == zlib:crc32(Z,ORIG)); 866 Error -> 867 io:format("Couldn't test external decompressor ~p\n", 868 [Error]) 869 end, 870 ok = zlib:close(Z), 871 ok; 872 false -> 873 {skipped,"No gzip in path"} 874 end. 875 876 877 878%% Test that (de)compress funcs work with standard tools, for example 879%% a chunk from a png file. 880compress_usage(Config) when is_list(Config) -> 881 compress_usage(compress_usage({get_arg,Config})); 882compress_usage({get_arg,Config}) -> 883 Out = get_data_dir(Config), 884 {ok,C1} = file:read_file(filename:join(Out,"png-compressed.zlib")), 885 {run,C1}; 886compress_usage({run,C1}) -> 887 Z = zlib:open(), 888 %% See that we can uncompress a file generated with external prog. 889 UC1 = zlib:uncompress(C1), 890 %% Check that the crc are correct. 891 ?m(4125865008,zlib:crc32(Z,UC1)), 892 C2 = zlib:compress(UC1), 893 UC2 = zlib:uncompress(C2), 894 %% Check that the crc are correct. 895 ?m(4125865008,zlib:crc32(Z,UC2)), 896 897 ok = zlib:close(Z), 898 899 D = [<<"We tests some partial">>, 900 <<"data, sent over">>, 901 <<"the stream">>, 902 <<"we check that we can unpack">>, 903 <<"every message we get">>], 904 905 ZC = zlib:open(), 906 ZU = zlib:open(), 907 Test = fun(finish, {_,Tot}) -> 908 Compressed = zlib:deflate(ZC, <<>>, finish), 909 Data = zlib:inflate(ZU, Compressed), 910 [Tot|Data]; 911 (Data, {Op,Tot}) -> 912 Compressed = zlib:deflate(ZC, Data, Op), 913 Res1 = ?m([Data],zlib:inflate(ZU, Compressed)), 914 {Op, [Tot|Res1]} 915 end, 916 zlib:deflateInit(ZC), 917 zlib:inflateInit(ZU), 918 T1 = lists:foldl(Test,{sync,[]},D++[finish]), 919 ?m(true, list_to_binary(D) == list_to_binary(T1)), 920 zlib:deflateEnd(ZC), 921 zlib:inflateEnd(ZU), 922 923 zlib:deflateInit(ZC), 924 zlib:inflateInit(ZU), 925 T2 = lists:foldl(Test,{full,[]},D++[finish]), 926 ?m(true, list_to_binary(D) == list_to_binary(T2)), 927 zlib:deflateEnd(ZC), 928 zlib:inflateEnd(ZU), 929 930 ok = zlib:close(ZC), 931 ok = zlib:close(ZU). 932 933 934%% Check that crc works as expected. 935crc(Config) when is_list(Config) -> 936 crc(crc({get_arg,Config})); 937crc({get_arg,Config}) -> 938 Out = get_data_dir(Config), 939 {ok,C1} = file:read_file(filename:join(Out,"zipdoc")), 940 {run,C1}; 941crc({run,C1}) -> 942 Z = zlib:open(), 943 Crc = zlib:crc32(Z, C1), 944 Bins = split_bin(C1,[]), 945 %%io:format("Length ~p ~p ~n", [length(Bins), [size(Bin) || Bin <- Bins]]), 946 Last = lists:last(Bins), 947 SCrc = lists:foldl(fun(Bin,Crc0) -> 948 Crc1 = zlib:crc32(Z, Crc0, Bin), 949 ?m(false, Crc == Crc1 andalso Bin /= Last), 950 Crc1 951 end, 0, Bins), 952 ?m(Crc,SCrc), 953 [First|Rest] = Bins, 954 Combine = fun(Bin, CS1) -> 955 CS2 = zlib:crc32(Z, Bin), 956 S2 = byte_size(Bin), 957 zlib:crc32_combine(Z,CS1,CS2,S2) 958 end, 959 Comb = lists:foldl(Combine, zlib:crc32(Z, First), Rest), 960 ?m(Crc,Comb), 961 ok = zlib:close(Z). 962 963%% Check that adler works as expected. 964adler(Config) when is_list(Config) -> 965 adler(adler({get_arg,Config})); 966adler({get_arg,Config}) -> 967 Out = get_data_dir(Config), 968 File1 = filename:join(Out,"zipdoc"), 969 {ok,C1} = file:read_file(File1), 970 {run,C1}; 971adler({run,C1}) -> 972 Z = zlib:open(), 973 ?m(1, zlib:adler32(Z,<<>>)), 974 Crc = zlib:adler32(Z, C1), 975 Bins = split_bin(C1,[]), 976 Last = lists:last(Bins), 977 SCrc = lists:foldl(fun(Bin,Crc0) -> 978 Crc1 = zlib:adler32(Z, Crc0, Bin), 979 ?m(false, Crc == Crc1 andalso Bin /= Last), 980 Crc1 981 end, zlib:adler32(Z,<<>>), Bins), 982 ?m(Crc,SCrc), 983 [First|Rest] = Bins, 984 Combine = fun(Bin, CS1) -> 985 CS2 = zlib:adler32(Z, Bin), 986 S2 = byte_size(Bin), 987 zlib:adler32_combine(Z,CS1,CS2,S2) 988 end, 989 Comb = lists:foldl(Combine, zlib:adler32(Z, First), Rest), 990 ?m(Crc,Comb), 991 ok = zlib:close(Z). 992 993%% Test dictionary usage. 994dictionary_usage(Config) when is_list(Config) -> 995 dictionary_usage(dictionary_usage({get_arg,Config})); 996dictionary_usage({get_arg,_Config}) -> 997 {run}; % no args 998dictionary_usage({run}) -> 999 Z1 = zlib:open(), 1000 Dict = <<"Anka">>, 1001 Data = <<"Kalle Anka">>, 1002 ?m(ok, zlib:deflateInit(Z1)), 1003 DictID = zlib:deflateSetDictionary(Z1, Dict), 1004 %% io:format("DictID = ~p\n", [DictID]), 1005 B1 = zlib:deflate(Z1, Data), 1006 B2 = zlib:deflate(Z1, <<>>, finish), 1007 ?m(ok, zlib:deflateEnd(Z1)), 1008 ?m(ok, zlib:close(Z1)), 1009 Compressed = list_to_binary([B1,B2]), 1010 %% io:format("~p\n", [Compressed]), 1011 1012 %% Now uncompress. 1013 Z2 = zlib:open(), 1014 ?m(ok, zlib:inflateInit(Z2)), 1015 1016 ?m(?EXIT({need_dictionary, DictID}), zlib:inflate(Z2, Compressed)), 1017 1018 ?m(ok, zlib:inflateSetDictionary(Z2, Dict)), 1019 ?m(ok, zlib:inflateSetDictionary(Z2, binary_to_list(Dict))), 1020 1021 Uncompressed = ?m(B when is_list(B), zlib:inflate(Z2, [])), 1022 1023 ?m(ok, zlib:inflateEnd(Z2)), 1024 ?m(ok, zlib:close(Z2)), 1025 ?m(Data, list_to_binary(Uncompressed)). 1026 1027split_bin(<<Part:1997/binary,Rest/binary>>, Acc) -> 1028 split_bin(Rest, [Part|Acc]); 1029split_bin(Last,Acc) -> 1030 lists:reverse([Last|Acc]). 1031 1032only_allow_owner(Config) when is_list(Config) -> 1033 Z = zlib:open(), 1034 Owner = self(), 1035 1036 ?m(ok, zlib:inflateInit(Z)), 1037 ?m(ok, zlib:inflateReset(Z)), 1038 1039 {Pid, Ref} = spawn_monitor( 1040 fun() -> 1041 ?m(?EXIT(not_on_controlling_process), zlib:inflateReset(Z)), 1042 Owner ! '$transfer_ownership', 1043 receive 1044 '$ownership_transferred' -> 1045 ?m(ok, zlib:inflateReset(Z)) 1046 after 200 -> 1047 ct:fail("Never received transfer signal.") 1048 end 1049 end), 1050 ownership_transfer_check(Z, Pid, Ref). 1051 1052ownership_transfer_check(Z, WorkerPid, Ref) -> 1053 receive 1054 '$transfer_ownership' -> 1055 zlib:set_controlling_process(Z, WorkerPid), 1056 WorkerPid ! '$ownership_transferred', 1057 ownership_transfer_check(Z, WorkerPid, Ref); 1058 {'DOWN', Ref, process, WorkerPid, normal} -> 1059 ok; 1060 {'DOWN', Ref, process, WorkerPid, Reason} -> 1061 ct:fail("Spawned worker crashed with reason ~p.", [Reason]) 1062 after 200 -> 1063 ct:fail("Spawned worker timed out.") 1064 end. 1065 1066sub_heap_binaries(Config) when is_list(Config) -> 1067 Compressed = zlib:compress(<<"gurka">>), 1068 ConfLen = erlang:length(Config), 1069 1070 HeapBin = <<ConfLen:8/integer, Compressed/binary>>, 1071 <<_:8/integer, SubHeapBin/binary>> = HeapBin, 1072 1073 ?m(<<"gurka">>, zlib:uncompress(SubHeapBin)), 1074 ok. 1075 1076%% Check concurrent access to zlib driver. 1077smp(Config) -> 1078 NumOfProcs = lists:min([8,erlang:system_info(schedulers)]), 1079 io:format("smp starting ~p workers\n",[NumOfProcs]), 1080 1081 %% Tests to run in parallel. 1082 Funcs = 1083 [zip_usage, gz_usage, compress_usage, dictionary_usage, 1084 crc, adler], 1085 1086 %% We get all function arguments here to avoid repeated parallel 1087 %% file read access. 1088 UsageArgs = 1089 list_to_tuple([{F, ?MODULE:F({get_arg,Config})} || F <- Funcs]), 1090 Parent = self(), 1091 1092 WorkerFun = 1093 fun() -> 1094 worker(rand:uniform(9999), UsageArgs, Parent) 1095 end, 1096 1097 Pids = [spawn_link(WorkerFun) || _ <- lists:seq(1, NumOfProcs)], 1098 wait_pids(Pids). 1099 1100worker(Seed, FnATpl, Parent) -> 1101 io:format("smp worker ~p, seed=~p~n",[self(),Seed]), 1102 rand:seed(exsplus, {Seed,Seed,Seed}), 1103 worker_loop(100, FnATpl), 1104 Parent ! self(). 1105 1106worker_loop(0, _FnATpl) -> 1107 large_deflate_do(), % the time consuming one as finale 1108 ok; 1109worker_loop(N, FnATpl) -> 1110 {F,A} = element(rand:uniform(tuple_size(FnATpl)), FnATpl), 1111 ?MODULE:F(A), 1112 worker_loop(N-1, FnATpl). 1113 1114wait_pids([]) -> 1115 ok; 1116wait_pids(Pids) -> 1117 receive 1118 Pid -> 1119 true = lists:member(Pid,Pids), 1120 Others = lists:delete(Pid,Pids), 1121 io:format("wait_pid got ~p, still waiting for ~p\n",[Pid,Others]), 1122 wait_pids(Others) 1123 end. 1124 1125 1126%% Deflate/inflate data with size close to multiple of internal buffer size. 1127otp_7359(_Config) -> 1128 %% Find compressed size 1129 ZTry = zlib:open(), 1130 ok = zlib:deflateInit(ZTry), 1131 ISize = zlib:getBufSize(ZTry), 1132 IData = list_to_binary([Byte band 255 || Byte <- lists:seq(1,ISize)]), 1133 ISize = byte_size(IData), 1134 1135 DSize = iolist_size(zlib:deflate(ZTry, IData, sync)), 1136 zlib:close(ZTry), 1137 1138 io:format("Deflated try ~p -> ~p bytes~n", [ISize, DSize]), 1139 1140 %% Try deflate and inflate with different internal buffer sizes 1141 ISpan = 1, 1142 DSpan = 10, % use larger span around deflated size as it may vary depending on buf size 1143 1144 Cases = [{DS,IS} || DMul<-[1,2], 1145 DS <- lists:seq((DSize div DMul)-DSpan, 1146 (DSize div DMul)+DSpan), 1147 IMul<-[1,2], 1148 IS <- lists:seq((ISize div IMul)-ISpan, 1149 (ISize div IMul)+ISpan)], 1150 1151 lists:foreach(fun(Case) -> otp_7359_def_inf(IData,Case) end, 1152 Cases). 1153 1154 1155otp_7359_def_inf(Data,{DefSize,InfSize}) -> 1156 %%io:format("Try: DefSize=~p InfSize=~p~n", [DefSize,InfSize]), 1157 ZDef = zlib:open(), 1158 ok = zlib:deflateInit(ZDef), 1159 ok = zlib:setBufSize(ZDef,DefSize), 1160 DefData = iolist_to_binary(zlib:deflate(ZDef, Data, sync)), 1161 %%io:format("Deflated ~p(~p) -> ~p(~p) bytes~n", 1162 %% [byte_size(Data), InfSize, byte_size(DefData), DefSize]), 1163 ok = zlib:close(ZDef), 1164 1165 ZInf = zlib:open(), 1166 ok = zlib:inflateInit(ZInf), 1167 ok = zlib:setBufSize(ZInf,InfSize), 1168 Data = iolist_to_binary(zlib:inflate(ZInf, DefData)), 1169 ok = zlib:close(ZInf), 1170 ok. 1171 1172otp_9981(Config) when is_list(Config) -> 1173 Ports = lists:sort(erlang:ports()), 1174 Invalid = <<"My invalid data">>, 1175 catch zlib:compress(invalid), 1176 Ports = lists:sort(erlang:ports()), 1177 catch zlib:uncompress(Invalid), 1178 Ports = lists:sort(erlang:ports()), 1179 catch zlib:zip(invalid), 1180 Ports = lists:sort(erlang:ports()), 1181 catch zlib:unzip(Invalid), 1182 Ports = lists:sort(erlang:ports()), 1183 catch zlib:gzip(invalid), 1184 Ports = lists:sort(erlang:ports()), 1185 catch zlib:gunzip(Invalid), 1186 Ports = lists:sort(erlang:ports()), 1187 ok. 1188 1189-define(BENCH_SIZE, (16 bsl 20)). 1190 1191-define(DECOMPRESS_BENCH(Name, What, Data), 1192 Name(Config) when is_list(Config) -> 1193 Uncompressed = Data, 1194 Compressed = zlib:compress(Uncompressed), 1195 What(Compressed, byte_size(Uncompressed))). 1196 1197-define(COMPRESS_BENCH(Name, What, Data), 1198 Name(Config) when is_list(Config) -> 1199 Compressed = Data, 1200 What(Compressed, byte_size(Compressed))). 1201 1202?DECOMPRESS_BENCH(inflate_bench_zeroed, throughput_bench_inflate, 1203 <<0:(8 * ?BENCH_SIZE)>>). 1204?DECOMPRESS_BENCH(inflate_bench_rand, throughput_bench_inflate, 1205 gen_determ_rand_bytes(?BENCH_SIZE)). 1206 1207?DECOMPRESS_BENCH(chunk_bench_zeroed, throughput_bench_chunk, 1208 <<0:(8 * ?BENCH_SIZE)>>). 1209?DECOMPRESS_BENCH(chunk_bench_rand, throughput_bench_chunk, 1210 gen_determ_rand_bytes(?BENCH_SIZE)). 1211 1212?COMPRESS_BENCH(deflate_bench_zeroed, throughput_bench_deflate, 1213 <<0:(8 * ?BENCH_SIZE)>>). 1214?COMPRESS_BENCH(deflate_bench_rand, throughput_bench_deflate, 1215 gen_determ_rand_bytes(?BENCH_SIZE)). 1216 1217throughput_bench_inflate(Compressed, Size) -> 1218 Z = zlib:open(), 1219 zlib:inflateInit(Z), 1220 1221 submit_throughput_results(Size, 1222 fun() -> 1223 zlib:inflate(Z, Compressed) 1224 end). 1225 1226throughput_bench_deflate(Uncompressed, Size) -> 1227 Z = zlib:open(), 1228 zlib:deflateInit(Z), 1229 1230 submit_throughput_results(Size, 1231 fun() -> 1232 zlib:deflate(Z, Uncompressed, finish) 1233 end). 1234 1235throughput_bench_chunk(Compressed, Size) -> 1236 Z = zlib:open(), 1237 zlib:inflateInit(Z), 1238 1239 ChunkLoop = 1240 fun 1241 Loop({more, _}) -> Loop(zlib:inflateChunk(Z)); 1242 Loop(_) -> ok 1243 end, 1244 1245 submit_throughput_results(Size, 1246 fun() -> 1247 ChunkLoop(zlib:inflateChunk(Z, Compressed)) 1248 end). 1249 1250submit_throughput_results(Size, Fun) -> 1251 TimeTaken = measure_perf_counter(Fun, millisecond), 1252 1253 KBPS = trunc((Size bsr 10) / (TimeTaken / 1000)), 1254 ct_event:notify(#event{ name = benchmark_data, data = [{value,KBPS}] }), 1255 {comment, io_lib:format("~p ms, ~p KBPS", [TimeTaken, KBPS])}. 1256 1257measure_perf_counter(Fun, Unit) -> 1258 Start = os:perf_counter(Unit), 1259 Fun(), 1260 os:perf_counter(Unit) - Start. 1261 1262%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1263%%% Helps with testing directly %%%%%%%%%%%%% 1264 1265get_data_dir(Config) -> 1266 try proplists:get_value(data_dir,Config) of 1267 undefined -> 1268 "./zlib_SUITE_data"; 1269 Dir -> 1270 Dir 1271 catch 1272 _:_ -> "./zlib_SUITE_data" 1273 end. 1274 1275%% Generates a bunch of statistically random bytes using the size as seed. 1276gen_determ_rand_bytes(Size) -> 1277 gen_determ_rand_bytes(Size, erlang:md5_init(), <<>>). 1278gen_determ_rand_bytes(Size, _Context, Acc) when Size =< 0 -> 1279 Acc; 1280gen_determ_rand_bytes(Size, Context0, Acc) when Size > 0 -> 1281 Context = erlang:md5_update(Context0, <<Size/integer>>), 1282 Checksum = erlang:md5_final(Context), 1283 gen_determ_rand_bytes(Size - 16, Context, <<Acc/binary, Checksum/binary>>). 1284