xref: /openbsd-src/gnu/usr.bin/perl/cpan/IO-Compress/t/cz-03zlib-v1.t (revision 5486feefcc8cb79b19e014ab332cc5dfd05b3b33)
1BEGIN {
2    if ($ENV{PERL_CORE}) {
3	chdir 't' if -d 't';
4	@INC = ("../lib", "lib/compress");
5    }
6}
7
8use lib qw(t t/compress);
9use strict;
10use warnings;
11use bytes;
12
13use Test::More ;
14use CompTestUtils;
15use Symbol;
16
17use constant ZLIB_1_2_12_0 => 0x12C0;
18
19BEGIN
20{
21    # use Test::NoWarnings, if available
22    my $extra = 0 ;
23    $extra = 1
24        if eval { require Test::NoWarnings ;  Test::NoWarnings->import; 1 };
25
26    my $count = 0 ;
27    if ($] < 5.005) {
28        $count = 453 ;
29    }
30    else {
31        $count = 471 ;
32    }
33
34
35    plan tests => $count + $extra ;
36
37    use_ok('Compress::Zlib', qw(:ALL memGunzip memGzip zlib_version));
38    use_ok('IO::Compress::Gzip::Constants') ;
39
40    use_ok('IO::Compress::Gzip', qw($GzipError)) ;
41}
42
43
44my $hello = <<EOM ;
45hello world
46this is a test
47EOM
48
49my $len   = length $hello ;
50
51# Check zlib_version and ZLIB_VERSION are the same.
52SKIP: {
53    skip "TEST_SKIP_VERSION_CHECK is set", 1
54        if $ENV{TEST_SKIP_VERSION_CHECK};
55    is Compress::Zlib::zlib_version, ZLIB_VERSION,
56        "ZLIB_VERSION matches Compress::Zlib::zlib_version" ;
57}
58
59# generate a long random string
60my $contents = '' ;
61foreach (1 .. 5000)
62  { $contents .= chr int rand 256 }
63
64my $x ;
65my $fil;
66
67# compress/uncompress tests
68# =========================
69
70eval { compress([1]); };
71ok $@ =~ m#not a scalar reference#
72    or print "# $@\n" ;;
73
74eval { uncompress([1]); };
75ok $@ =~ m#not a scalar reference#
76    or print "# $@\n" ;;
77
78$hello = "hello mum" ;
79my $keep_hello = $hello ;
80
81my $compr = compress($hello) ;
82ok $compr ne "" ;
83
84my $keep_compr = $compr ;
85
86my $uncompr = uncompress ($compr) ;
87
88ok $hello eq $uncompr ;
89
90ok $hello eq $keep_hello ;
91ok $compr eq $keep_compr ;
92
93# compress a number
94$hello = 7890 ;
95$keep_hello = $hello ;
96
97$compr = compress($hello) ;
98ok $compr ne "" ;
99
100$keep_compr = $compr ;
101
102$uncompr = uncompress ($compr) ;
103
104ok $hello eq $uncompr ;
105
106ok $hello eq $keep_hello ;
107ok $compr eq $keep_compr ;
108
109# bigger compress
110
111$compr = compress ($contents) ;
112ok $compr ne "" ;
113
114$uncompr = uncompress ($compr) ;
115
116ok $contents eq $uncompr ;
117
118# buffer reference
119
120$compr = compress(\$hello) ;
121ok $compr ne "" ;
122
123
124$uncompr = uncompress (\$compr) ;
125ok $hello eq $uncompr ;
126
127# bad level
128$compr = compress($hello, 1000) ;
129ok ! defined $compr;
130
131# change level
132$compr = compress($hello, Z_BEST_COMPRESSION) ;
133ok defined $compr;
134$uncompr = uncompress (\$compr) ;
135ok $hello eq $uncompr ;
136
137# corrupt data
138$compr = compress(\$hello) ;
139ok $compr ne "" ;
140
141substr($compr,0, 1) = "\xFF";
142ok !defined uncompress (\$compr) ;
143
144# deflate/inflate - small buffer
145# ==============================
146
147$hello = "I am a HAL 9000 computer" ;
148my @hello = split('', $hello) ;
149my ($err, $X, $status);
150
151ok  (($x, $err) = deflateInit( {-Bufsize => 1} ) ) ;
152ok $x ;
153ok $err == Z_OK ;
154
155my $Answer = '';
156foreach (@hello)
157{
158    ($X, $status) = $x->deflate($_) ;
159    last unless $status == Z_OK ;
160
161    $Answer .= $X ;
162}
163
164ok $status == Z_OK ;
165
166ok    ((($X, $status) = $x->flush())[1] == Z_OK ) ;
167$Answer .= $X ;
168
169
170my @Answer = split('', $Answer) ;
171
172my $k;
173ok (($k, $err) = inflateInit( {-Bufsize => 1}) ) ;
174ok $k ;
175ok $err == Z_OK ;
176
177my $GOT = '';
178my $Z;
179foreach (@Answer)
180{
181    ($Z, $status) = $k->inflate($_) ;
182    $GOT .= $Z ;
183    last if $status == Z_STREAM_END or $status != Z_OK ;
184
185}
186
187ok $status == Z_STREAM_END ;
188ok $GOT eq $hello ;
189
190
191title 'deflate/inflate - small buffer with a number';
192# ==============================
193
194$hello = 6529 ;
195
196ok (($x, $err) = deflateInit( {-Bufsize => 1} ) ) ;
197ok $x ;
198ok $err == Z_OK ;
199
200ok !defined $x->msg() ;
201ok $x->total_in() == 0 ;
202ok $x->total_out() == 0 ;
203$Answer = '';
204{
205    ($X, $status) = $x->deflate($hello) ;
206
207    $Answer .= $X ;
208}
209
210ok $status == Z_OK ;
211
212ok   ((($X, $status) = $x->flush())[1] == Z_OK ) ;
213$Answer .= $X ;
214
215ok !defined $x->msg() ;
216ok $x->total_in() == length $hello ;
217ok $x->total_out() == length $Answer ;
218
219
220@Answer = split('', $Answer) ;
221
222ok (($k, $err) = inflateInit( {-Bufsize => 1}) ) ;
223ok $k ;
224ok $err == Z_OK ;
225
226ok !defined $k->msg() ;
227ok $k->total_in() == 0 ;
228ok $k->total_out() == 0 ;
229
230$GOT = '';
231foreach (@Answer)
232{
233    ($Z, $status) = $k->inflate($_) ;
234    $GOT .= $Z ;
235    last if $status == Z_STREAM_END or $status != Z_OK ;
236
237}
238
239ok $status == Z_STREAM_END ;
240ok $GOT eq $hello ;
241
242ok !defined $k->msg() ;
243is $k->total_in(), length $Answer ;
244ok $k->total_out() == length $hello ;
245
246
247
248title 'deflate/inflate - larger buffer';
249# ==============================
250
251
252ok $x = deflateInit() ;
253
254ok ((($X, $status) = $x->deflate($contents))[1] == Z_OK) ;
255
256my $Y = $X ;
257
258
259ok ((($X, $status) = $x->flush() )[1] == Z_OK ) ;
260$Y .= $X ;
261
262
263
264ok $k = inflateInit() ;
265
266($Z, $status) = $k->inflate($Y) ;
267
268ok $status == Z_STREAM_END ;
269ok $contents eq $Z ;
270
271title 'deflate/inflate - preset dictionary';
272# ===================================
273
274my $dictionary = "hello" ;
275ok $x = deflateInit({-Level => Z_BEST_COMPRESSION,
276			 -Dictionary => $dictionary}) ;
277
278my $dictID = $x->dict_adler() ;
279
280($X, $status) = $x->deflate($hello) ;
281ok $status == Z_OK ;
282($Y, $status) = $x->flush() ;
283ok $status == Z_OK ;
284$X .= $Y ;
285$x = 0 ;
286
287ok $k = inflateInit(-Dictionary => $dictionary) ;
288
289($Z, $status) = $k->inflate($X);
290ok $status == Z_STREAM_END ;
291ok $k->dict_adler() == $dictID;
292ok $hello eq $Z ;
293
294#$Z='';
295#while (1) {
296#    ($Z, $status) = $k->inflate($X) ;
297#    last if $status == Z_STREAM_END or $status != Z_OK ;
298#print "status=[$status] hello=[$hello] Z=[$Z]\n";
299#}
300#ok $status == Z_STREAM_END ;
301#ok $hello eq $Z
302# or print "status=[$status] hello=[$hello] Z=[$Z]\n";
303
304
305
306
307
308
309title 'inflate - check remaining buffer after Z_STREAM_END';
310# ===================================================
311
312{
313    ok $x = deflateInit(-Level => Z_BEST_COMPRESSION ) ;
314
315    ($X, $status) = $x->deflate($hello) ;
316    ok $status == Z_OK ;
317    ($Y, $status) = $x->flush() ;
318    ok $status == Z_OK ;
319    $X .= $Y ;
320    $x = 0 ;
321
322    ok $k = inflateInit()  ;
323
324    my $first = substr($X, 0, 2) ;
325    my $last  = substr($X, 2) ;
326    ($Z, $status) = $k->inflate($first);
327    ok $status == Z_OK ;
328    ok $first eq "" ;
329
330    $last .= "appendage" ;
331    my $T;
332    ($T, $status) = $k->inflate($last);
333    ok $status == Z_STREAM_END ;
334    ok $hello eq $Z . $T ;
335    ok $last eq "appendage" ;
336
337}
338
339title 'memGzip & memGunzip';
340{
341    my ($name, $name1, $name2, $name3);
342    my $lex = LexFile->new( $name, $name1, $name2, $name3 );
343    my $buffer = <<EOM;
344some sample
345text
346
347EOM
348
349    my $len = length $buffer ;
350    my ($x, $uncomp) ;
351
352
353    # create an in-memory gzip file
354    my $dest = memGzip($buffer) ;
355    ok length $dest ;
356    is $gzerrno, 0;
357
358    # write it to disk
359    ok open(FH, ">$name") ;
360    binmode(FH);
361    print FH $dest ;
362    close FH ;
363
364    # uncompress with gzopen
365    ok my $fil = gzopen($name, "rb") ;
366
367    is $fil->gzread($uncomp, 0), 0 ;
368    ok (($x = $fil->gzread($uncomp)) == $len) ;
369
370    ok ! $fil->gzclose ;
371
372    ok $uncomp eq $buffer ;
373
374    #1 while unlink $name ;
375
376    # now check that memGunzip can deal with it.
377    my $ungzip = memGunzip($dest) ;
378    ok defined $ungzip ;
379    ok $buffer eq $ungzip ;
380    is $gzerrno, 0;
381
382    # now do the same but use a reference
383
384    $dest = memGzip(\$buffer) ;
385    ok length $dest ;
386    is $gzerrno, 0;
387
388    # write it to disk
389    ok open(FH, ">$name1") ;
390    binmode(FH);
391    print FH $dest ;
392    close FH ;
393
394    # uncompress with gzopen
395    ok $fil = gzopen($name1, "rb") ;
396
397    ok (($x = $fil->gzread($uncomp)) == $len) ;
398
399    ok ! $fil->gzclose ;
400
401    ok $uncomp eq $buffer ;
402
403    # now check that memGunzip can deal with it.
404    my $keep = $dest;
405    $ungzip = memGunzip(\$dest) ;
406    is $gzerrno, 0;
407    ok defined $ungzip ;
408    ok $buffer eq $ungzip ;
409
410    # check memGunzip can cope with missing gzip trailer
411    my $minimal = substr($keep, 0, -1) ;
412    $ungzip = memGunzip(\$minimal) ;
413    ok defined $ungzip ;
414    ok $buffer eq $ungzip ;
415    is $gzerrno, 0;
416
417    $minimal = substr($keep, 0, -2) ;
418    $ungzip = memGunzip(\$minimal) ;
419    ok defined $ungzip ;
420    ok $buffer eq $ungzip ;
421    is $gzerrno, 0;
422
423    $minimal = substr($keep, 0, -3) ;
424    $ungzip = memGunzip(\$minimal) ;
425    ok defined $ungzip ;
426    ok $buffer eq $ungzip ;
427    is $gzerrno, 0;
428
429    $minimal = substr($keep, 0, -4) ;
430    $ungzip = memGunzip(\$minimal) ;
431    ok defined $ungzip ;
432    ok $buffer eq $ungzip ;
433    is $gzerrno, 0;
434
435    $minimal = substr($keep, 0, -5) ;
436    $ungzip = memGunzip(\$minimal) ;
437    ok defined $ungzip ;
438    ok $buffer eq $ungzip ;
439    is $gzerrno, 0;
440
441    $minimal = substr($keep, 0, -6) ;
442    $ungzip = memGunzip(\$minimal) ;
443    ok defined $ungzip ;
444    ok $buffer eq $ungzip ;
445    is $gzerrno, 0;
446
447    $minimal = substr($keep, 0, -7) ;
448    $ungzip = memGunzip(\$minimal) ;
449    ok defined $ungzip ;
450    ok $buffer eq $ungzip ;
451    is $gzerrno, 0;
452
453    $minimal = substr($keep, 0, -8) ;
454    $ungzip = memGunzip(\$minimal) ;
455    ok defined $ungzip ;
456    ok $buffer eq $ungzip ;
457    is $gzerrno, 0;
458
459    $minimal = substr($keep, 0, -9) ;
460    $ungzip = memGunzip(\$minimal) ;
461    ok ! defined $ungzip ;
462    cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
463
464
465    #1 while unlink $name ;
466
467    # check corrupt header -- too short
468    $dest = "x" ;
469    my $result = memGunzip($dest) ;
470    ok !defined $result ;
471    cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
472
473    # check corrupt header -- full of junk
474    $dest = "x" x 200 ;
475    $result = memGunzip($dest) ;
476    ok !defined $result ;
477    cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
478
479    # corrupt header - 1st byte wrong
480    my $bad = $keep ;
481    substr($bad, 0, 1) = "\xFF" ;
482    $ungzip = memGunzip(\$bad) ;
483    ok ! defined $ungzip ;
484    cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
485
486    # corrupt header - 2st byte wrong
487    $bad = $keep ;
488    substr($bad, 1, 1) = "\xFF" ;
489    $ungzip = memGunzip(\$bad) ;
490    ok ! defined $ungzip ;
491    cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
492
493    # corrupt header - method not deflated
494    $bad = $keep ;
495    substr($bad, 2, 1) = "\xFF" ;
496    $ungzip = memGunzip(\$bad) ;
497    ok ! defined $ungzip ;
498    cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
499
500    # corrupt header - reserved bits used
501    $bad = $keep ;
502    substr($bad, 3, 1) = "\xFF" ;
503    $ungzip = memGunzip(\$bad) ;
504    ok ! defined $ungzip ;
505    cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
506
507    # corrupt trailer - length wrong
508    $bad = $keep ;
509    substr($bad, -8, 4) = "\xFF" x 4 ;
510    $ungzip = memGunzip(\$bad) ;
511    ok ! defined $ungzip ;
512    cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
513
514    # corrupt trailer - CRC wrong
515    $bad = $keep ;
516    substr($bad, -4, 4) = "\xFF" x 4 ;
517    $ungzip = memGunzip(\$bad) ;
518    ok ! defined $ungzip ;
519    cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
520}
521
522{
523    title "Check all bytes can be handled";
524
525    my $lex = LexFile->new( my $name );
526    my $data = join '', map { chr } 0x00 .. 0xFF;
527    $data .= "\r\nabd\r\n";
528
529    my $fil;
530    ok $fil = gzopen($name, "wb") ;
531    is $fil->gzwrite($data), length $data ;
532    ok ! $fil->gzclose();
533
534    my $input;
535    ok $fil = gzopen($name, "rb") ;
536    is $fil->gzread($input), length $data ;
537    ok ! $fil->gzclose();
538    ok $input eq $data;
539
540    title "Check all bytes can be handled - transparent mode";
541    writeFile($name, $data);
542    ok $fil = gzopen($name, "rb") ;
543    is $fil->gzread($input), length $data ;
544    ok ! $fil->gzclose();
545    ok $input eq $data;
546
547}
548
549title 'memGunzip with a gzopen created file';
550{
551    my $name = "test.gz" ;
552    my $buffer = <<EOM;
553some sample
554text
555
556EOM
557
558    ok $fil = gzopen($name, "wb") ;
559
560    ok $fil->gzwrite($buffer) == length $buffer ;
561
562    ok ! $fil->gzclose ;
563
564    my $compr = readFile($name);
565    ok length $compr ;
566    my $unc = memGunzip($compr) ;
567    is $gzerrno, 0;
568    ok defined $unc ;
569    ok $buffer eq $unc ;
570    1 while unlink $name ;
571}
572
573{
574
575    # Check - MAX_WBITS
576    # =================
577
578    $hello = "Test test test test test";
579    @hello = split('', $hello) ;
580
581    ok (($x, $err) = deflateInit( -Bufsize => 1, -WindowBits => -MAX_WBITS() ) ) ;
582    ok $x ;
583    ok $err == Z_OK ;
584
585    $Answer = '';
586    foreach (@hello)
587    {
588        ($X, $status) = $x->deflate($_) ;
589        last unless $status == Z_OK ;
590
591        $Answer .= $X ;
592    }
593
594    ok $status == Z_OK ;
595
596    ok   ((($X, $status) = $x->flush())[1] == Z_OK ) ;
597    $Answer .= $X ;
598
599
600    @Answer = split('', $Answer) ;
601    # Undocumented corner -- extra byte needed to get inflate to return
602    # Z_STREAM_END when done.
603    push @Answer, " " ;
604
605    ok (($k, $err) = inflateInit(-Bufsize => 1, -WindowBits => -MAX_WBITS()) ) ;
606    ok $k ;
607    ok $err == Z_OK ;
608
609    $GOT = '';
610    foreach (@Answer)
611    {
612        ($Z, $status) = $k->inflate($_) ;
613        $GOT .= $Z ;
614        last if $status == Z_STREAM_END or $status != Z_OK ;
615
616    }
617
618    ok $status == Z_STREAM_END ;
619    ok $GOT eq $hello ;
620
621}
622
623{
624    # inflateSync
625
626    # create a deflate stream with flush points
627
628    my $hello = "I am a HAL 9000 computer" x 2001 ;
629    my $goodbye = "Will I dream?" x 2010;
630    my ($err, $answer, $X, $status, $Answer);
631
632    ok (($x, $err) = deflateInit() ) ;
633    ok $x ;
634    ok $err == Z_OK ;
635
636    ($Answer, $status) = $x->deflate($hello) ;
637    ok $status == Z_OK ;
638
639    # create a flush point
640    ok ((($X, $status) = $x->flush(Z_FULL_FLUSH))[1] == Z_OK ) ;
641    $Answer .= $X ;
642
643    ($X, $status) = $x->deflate($goodbye) ;
644    ok $status == Z_OK ;
645    $Answer .= $X ;
646
647    ok ((($X, $status) = $x->flush())[1] == Z_OK ) ;
648    $Answer .= $X ;
649
650    my ($first, @Answer) = split('', $Answer) ;
651
652    my $k;
653    ok (($k, $err) = inflateInit()) ;
654    ok $k ;
655    ok $err == Z_OK ;
656
657    ($Z, $status) = $k->inflate($first) ;
658    ok $status == Z_OK ;
659
660    # skip to the first flush point.
661    while (@Answer)
662    {
663        my $byte = shift @Answer;
664        $status = $k->inflateSync($byte) ;
665        last unless $status == Z_DATA_ERROR;
666
667    }
668
669    ok $status == Z_OK;
670
671    my $GOT = '';
672    my $Z = '';
673    foreach (@Answer)
674    {
675        my $Z = '';
676        ($Z, $status) = $k->inflate($_) ;
677        $GOT .= $Z if defined $Z ;
678        # print "x $status\n";
679        last if $status == Z_STREAM_END or $status != Z_OK ;
680
681    }
682
683    # zlib 1.0.9 returns Z_STREAM_END here, all others return Z_DATA_ERROR
684    ok $status == Z_DATA_ERROR || $status == Z_STREAM_END ;
685    ok $GOT eq $goodbye ;
686
687
688    # Check inflateSync leaves good data in buffer
689    $Answer =~ /^(.)(.*)$/ ;
690    my ($initial, $rest) = ($1, $2);
691
692
693    ok (($k, $err) = inflateInit()) ;
694    ok $k ;
695    ok $err == Z_OK ;
696
697    ($Z, $status) = $k->inflate($initial) ;
698    ok $status == Z_OK ;
699
700    $status = $k->inflateSync($rest) ;
701    ok $status == Z_OK;
702
703    ($GOT, $status) = $k->inflate($rest) ;
704
705    # Z_STREAM_END returned by 1.12.2, Z_DATA_ERROR for older zlib
706    # always Z_STREAM_ENDin zlib_ng
707    if (ZLIB_VERNUM >= ZLIB_1_2_12_0 || Compress::Raw::Zlib::is_zlibng)
708    {
709        cmp_ok $status, '==', Z_STREAM_END ;
710    }
711    else
712    {
713        cmp_ok $status, '==', Z_DATA_ERROR ;
714    }
715
716    ok $Z . $GOT eq $goodbye ;
717}
718
719{
720    # deflateParams
721
722    my $hello = "I am a HAL 9000 computer" x 2001 ;
723    my $goodbye = "Will I dream?" x 2010;
724    my ($input, $err, $answer, $X, $status, $Answer);
725
726    ok (($x, $err) = deflateInit(-Level    => Z_BEST_COMPRESSION,
727                                     -Strategy => Z_DEFAULT_STRATEGY) ) ;
728    ok $x ;
729    ok $err == Z_OK ;
730
731    ok $x->get_Level()    == Z_BEST_COMPRESSION;
732    ok $x->get_Strategy() == Z_DEFAULT_STRATEGY;
733
734    ($Answer, $status) = $x->deflate($hello) ;
735    ok $status == Z_OK ;
736    $input .= $hello;
737
738    # error cases
739    eval { $x->deflateParams() };
740    #like $@, mkErr("^Compress::Raw::Zlib::deflateParams needs Level and/or Strategy");
741    like $@, "/^Compress::Raw::Zlib::deflateParams needs Level and/or Strategy/";
742
743    eval { $x->deflateParams(-Joe => 3) };
744    like $@, "/^Compress::Raw::Zlib::deflateStream::deflateParams: unknown key value/";
745    #like $@, mkErr("^Compress::Raw::Zlib::deflateStream::deflateParams: unknown key value(s) Joe");
746    #ok $@ =~ /^Compress::Zlib::deflateStream::deflateParams: unknown key value\(s\) Joe at/
747    #    or print "# $@\n" ;
748
749    ok $x->get_Level()    == Z_BEST_COMPRESSION;
750    ok $x->get_Strategy() == Z_DEFAULT_STRATEGY;
751
752    # change both Level & Strategy
753    $status = $x->deflateParams(-Level => Z_BEST_SPEED, -Strategy => Z_HUFFMAN_ONLY) ;
754    ok $status == Z_OK ;
755
756    ok $x->get_Level()    == Z_BEST_SPEED;
757    ok $x->get_Strategy() == Z_HUFFMAN_ONLY;
758
759    ($X, $status) = $x->deflate($goodbye) ;
760    ok $status == Z_OK ;
761    $Answer .= $X ;
762    $input .= $goodbye;
763
764    # change only Level
765    $status = $x->deflateParams(-Level => Z_NO_COMPRESSION) ;
766    ok $status == Z_OK ;
767
768    ok $x->get_Level()    == Z_NO_COMPRESSION;
769    ok $x->get_Strategy() == Z_HUFFMAN_ONLY;
770
771    ($X, $status) = $x->deflate($goodbye) ;
772    ok $status == Z_OK ;
773    $Answer .= $X ;
774    $input .= $goodbye;
775
776    # change only Strategy
777    $status = $x->deflateParams(-Strategy => Z_FILTERED) ;
778    ok $status == Z_OK ;
779
780    ok $x->get_Level()    == Z_NO_COMPRESSION;
781    ok $x->get_Strategy() == Z_FILTERED;
782
783    ($X, $status) = $x->deflate($goodbye) ;
784    ok $status == Z_OK ;
785    $Answer .= $X ;
786    $input .= $goodbye;
787
788    ok ((($X, $status) = $x->flush())[1] == Z_OK ) ;
789    $Answer .= $X ;
790
791    my ($first, @Answer) = split('', $Answer) ;
792
793    my $k;
794    ok (($k, $err) = inflateInit()) ;
795    ok $k ;
796    ok $err == Z_OK ;
797
798    ($Z, $status) = $k->inflate($Answer) ;
799
800    ok $status == Z_STREAM_END
801        or print "# status $status\n";
802    ok $Z  eq $input ;
803}
804
805{
806    # error cases
807
808    eval { deflateInit(-Level) };
809    like $@, '/^Compress::Zlib::deflateInit: Expected even number of parameters, got 1/';
810
811    eval { inflateInit(-Level) };
812    like $@, '/^Compress::Zlib::inflateInit: Expected even number of parameters, got 1/';
813
814    eval { deflateInit(-Joe => 1) };
815    ok $@ =~ /^Compress::Zlib::deflateInit: unknown key value\(s\) Joe at/;
816
817    eval { inflateInit(-Joe => 1) };
818    ok $@ =~ /^Compress::Zlib::inflateInit: unknown key value\(s\) Joe at/;
819
820    eval { deflateInit(-Bufsize => 0) };
821    ok $@ =~ /^.*?: Bufsize must be >= 1, you specified 0 at/;
822
823    eval { inflateInit(-Bufsize => 0) };
824    ok $@ =~ /^.*?: Bufsize must be >= 1, you specified 0 at/;
825
826    eval { deflateInit(-Bufsize => -1) };
827    #ok $@ =~ /^.*?: Bufsize must be >= 1, you specified -1 at/;
828    ok $@ =~ /^Compress::Zlib::deflateInit: Parameter 'Bufsize' must be an unsigned int, got '-1'/;
829
830    eval { inflateInit(-Bufsize => -1) };
831    ok $@ =~ /^Compress::Zlib::inflateInit: Parameter 'Bufsize' must be an unsigned int, got '-1'/;
832
833    eval { deflateInit(-Bufsize => "xxx") };
834    ok $@ =~ /^Compress::Zlib::deflateInit: Parameter 'Bufsize' must be an unsigned int, got 'xxx'/;
835
836    eval { inflateInit(-Bufsize => "xxx") };
837    ok $@ =~ /^Compress::Zlib::inflateInit: Parameter 'Bufsize' must be an unsigned int, got 'xxx'/;
838
839    eval { gzopen([], 0) ; }  ;
840    ok $@ =~ /^gzopen: file parameter is not a filehandle or filename at/
841	or print "# $@\n" ;
842
843#    my $x = Symbol::gensym() ;
844#    eval { gzopen($x, 0) ; }  ;
845#    ok $@ =~ /^gzopen: file parameter is not a filehandle or filename at/
846#	or print "# $@\n" ;
847
848}
849
850if ($] >= 5.005)
851{
852    # test inflate with a substr
853
854    ok my $x = deflateInit() ;
855
856    ok ((my ($X, $status) = $x->deflate($contents))[1] == Z_OK) ;
857
858    my $Y = $X ;
859
860
861
862    ok ((($X, $status) = $x->flush() )[1] == Z_OK ) ;
863    $Y .= $X ;
864
865    my $append = "Appended" ;
866    $Y .= $append ;
867
868    ok $k = inflateInit() ;
869
870    #($Z, $status) = $k->inflate(substr($Y, 0, -1)) ;
871    ($Z, $status) = $k->inflate(substr($Y, 0)) ;
872
873    ok $status == Z_STREAM_END ;
874    ok $contents eq $Z ;
875    is $Y, $append;
876
877}
878
879if ($] >= 5.005)
880{
881    # deflate/inflate in scalar context
882
883    ok my $x = deflateInit() ;
884
885    my $X = $x->deflate($contents);
886
887    my $Y = $X ;
888
889
890
891    $X = $x->flush();
892    $Y .= $X ;
893
894    my $append = "Appended" ;
895    $Y .= $append ;
896
897    ok $k = inflateInit() ;
898
899    $Z = $k->inflate(substr($Y, 0, -1)) ;
900    #$Z = $k->inflate(substr($Y, 0)) ;
901
902    ok $contents eq $Z ;
903    is $Y, $append;
904
905}
906
907{
908    title 'CRC32' ;
909
910    # CRC32 of this data should have the high bit set
911    # value in ascii is ZgRNtjgSUW
912    my $data = "\x5a\x67\x52\x4e\x74\x6a\x67\x53\x55\x57";
913    my $expected_crc = 0xCF707A2B ; # 3480255019
914
915    my $crc = crc32($data) ;
916    is $crc, $expected_crc;
917}
918
919{
920    title 'Adler32' ;
921
922    # adler of this data should have the high bit set
923    # value in ascii is lpscOVsAJiUfNComkOfWYBcPhHZ[bT
924    my $data = "\x6c\x70\x73\x63\x4f\x56\x73\x41\x4a\x69\x55\x66" .
925               "\x4e\x43\x6f\x6d\x6b\x4f\x66\x57\x59\x42\x63\x50" .
926               "\x68\x48\x5a\x5b\x62\x54";
927    my $expected_crc = 0xAAD60AC7 ; # 2866154183
928    my $crc = adler32($data) ;
929    is $crc, $expected_crc;
930}
931
932{
933    # memGunzip - input > 4K
934
935    my $contents = '' ;
936    foreach (1 .. 20000)
937      { $contents .= chr int rand 256 }
938
939    ok my $compressed = memGzip(\$contents) ;
940    is $gzerrno, 0;
941
942    ok length $compressed > 4096 ;
943    ok my $out = memGunzip(\$compressed) ;
944    is $gzerrno, 0;
945
946    ok $contents eq $out ;
947    is length $out, length $contents ;
948
949
950}
951
952
953{
954    # memGunzip Header Corruption Tests
955
956    my $string = <<EOM;
957some text
958EOM
959
960    my $good ;
961    ok my $x = IO::Compress::Gzip->new( \$good, Append => 1, -HeaderCRC => 1 );
962    ok $x->write($string) ;
963    ok  $x->close ;
964
965    {
966        title "Header Corruption - Fingerprint wrong 1st byte" ;
967        my $buffer = $good ;
968        substr($buffer, 0, 1) = 'x' ;
969
970        ok ! memGunzip(\$buffer) ;
971        cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
972    }
973
974    {
975        title "Header Corruption - Fingerprint wrong 2nd byte" ;
976        my $buffer = $good ;
977        substr($buffer, 1, 1) = "\xFF" ;
978
979        ok ! memGunzip(\$buffer) ;
980        cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
981    }
982
983    {
984        title "Header Corruption - CM not 8";
985        my $buffer = $good ;
986        substr($buffer, 2, 1) = 'x' ;
987
988        ok ! memGunzip(\$buffer) ;
989        cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
990    }
991
992    {
993        title "Header Corruption - Use of Reserved Flags";
994        my $buffer = $good ;
995        substr($buffer, 3, 1) = "\xff";
996
997        ok ! memGunzip(\$buffer) ;
998        cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
999    }
1000
1001}
1002
1003for my $index ( GZIP_MIN_HEADER_SIZE + 1 ..  GZIP_MIN_HEADER_SIZE + GZIP_FEXTRA_HEADER_SIZE + 1)
1004{
1005    title "Header Corruption - Truncated in Extra";
1006    my $string = <<EOM;
1007some text
1008EOM
1009
1010    my $truncated ;
1011    ok  my $x = IO::Compress::Gzip->new( \$truncated, Append => 1, -HeaderCRC => 1, Strict => 0,
1012				-ExtraField => "hello" x 10 );
1013    ok  $x->write($string) ;
1014    ok  $x->close ;
1015
1016    substr($truncated, $index) = '' ;
1017
1018    ok ! memGunzip(\$truncated) ;
1019    cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
1020
1021
1022}
1023
1024my $Name = "fred" ;
1025for my $index ( GZIP_MIN_HEADER_SIZE ..  GZIP_MIN_HEADER_SIZE + length($Name) -1)
1026{
1027    title "Header Corruption - Truncated in Name";
1028    my $string = <<EOM;
1029some text
1030EOM
1031
1032    my $truncated ;
1033    ok  my $x = IO::Compress::Gzip->new( \$truncated, Append => 1, -Name => $Name );
1034    ok  $x->write($string) ;
1035    ok  $x->close ;
1036
1037    substr($truncated, $index) = '' ;
1038
1039    ok ! memGunzip(\$truncated) ;
1040    cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
1041}
1042
1043my $Comment = "comment" ;
1044for my $index ( GZIP_MIN_HEADER_SIZE ..  GZIP_MIN_HEADER_SIZE + length($Comment) -1)
1045{
1046    title "Header Corruption - Truncated in Comment";
1047    my $string = <<EOM;
1048some text
1049EOM
1050
1051    my $truncated ;
1052    ok  my $x = IO::Compress::Gzip->new( \$truncated, -Comment => $Comment );
1053    ok  $x->write($string) ;
1054    ok  $x->close ;
1055
1056    substr($truncated, $index) = '' ;
1057    ok ! memGunzip(\$truncated) ;
1058    cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
1059}
1060
1061for my $index ( GZIP_MIN_HEADER_SIZE ..  GZIP_MIN_HEADER_SIZE + GZIP_FHCRC_SIZE -1)
1062{
1063    title "Header Corruption - Truncated in CRC";
1064    my $string = <<EOM;
1065some text
1066EOM
1067
1068    my $truncated ;
1069    ok  my $x = IO::Compress::Gzip->new( \$truncated, -HeaderCRC => 1 );
1070    ok  $x->write($string) ;
1071    ok  $x->close ;
1072
1073    substr($truncated, $index) = '' ;
1074
1075    ok ! memGunzip(\$truncated) ;
1076    cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
1077}
1078
1079{
1080    title "memGunzip can cope with a gzip header with all possible fields";
1081    my $string = <<EOM;
1082some text
1083EOM
1084
1085    my $buffer ;
1086    ok  my $x = IO::Compress::Gzip->new( \$buffer,
1087                             -Append     => 1,
1088                             -Strict     => 0,
1089                             -HeaderCRC  => 1,
1090                             -Name       => "Fred",
1091                             -ExtraField => "Extra",
1092                             -Comment    => 'Comment' );
1093    ok  $x->write($string) ;
1094    ok  $x->close ;
1095
1096    ok defined $buffer ;
1097
1098    ok my $got = memGunzip($buffer)
1099        or diag "gzerrno is $gzerrno" ;
1100    is $got, $string ;
1101    is $gzerrno, 0;
1102}
1103
1104
1105{
1106    # Trailer Corruption tests
1107
1108    my $string = <<EOM;
1109some text
1110EOM
1111
1112    my $good ;
1113    ok  my $x = IO::Compress::Gzip->new( \$good, Append => 1 );
1114    ok  $x->write($string) ;
1115    ok  $x->close ;
1116
1117    foreach my $trim (-8 .. -1)
1118    {
1119        my $got = $trim + 8 ;
1120        title "Trailer Corruption - Trailer truncated to $got bytes" ;
1121        my $buffer = $good ;
1122
1123        substr($buffer, $trim) = '';
1124
1125        ok my $u = memGunzip(\$buffer) ;
1126        is $gzerrno, 0;
1127        ok $u eq $string;
1128
1129    }
1130
1131    {
1132        title "Trailer Corruption - Length Wrong, CRC Correct" ;
1133        my $buffer = $good ;
1134        substr($buffer, -4, 4) = pack('V', 1234);
1135
1136        ok ! memGunzip(\$buffer) ;
1137        cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
1138    }
1139
1140    {
1141        title "Trailer Corruption - Length Wrong, CRC Wrong" ;
1142        my $buffer = $good ;
1143        substr($buffer, -4, 4) = pack('V', 1234);
1144        substr($buffer, -8, 4) = pack('V', 1234);
1145
1146        ok ! memGunzip(\$buffer) ;
1147        cmp_ok $gzerrno, "==", Z_DATA_ERROR ;
1148
1149    }
1150}
1151
1152
1153sub slurp
1154{
1155    my $name = shift ;
1156
1157    my $input;
1158    my $fil = gzopen($name, "rb") ;
1159    ok $fil , "opened $name";
1160    cmp_ok $fil->gzread($input, 50000), ">", 0, "read more than zero bytes";
1161    ok ! $fil->gzclose(), "closed ok";
1162
1163    return $input;
1164}
1165
1166sub trickle
1167{
1168    my $name = shift ;
1169
1170    my $got;
1171    my $input;
1172    $fil = gzopen($name, "rb") ;
1173    ok $fil, "opened ok";
1174    while ($fil->gzread($input, 50000) > 0)
1175    {
1176        $got .= $input;
1177        $input = '';
1178    }
1179    ok ! $fil->gzclose(), "closed ok";
1180
1181    return $got;
1182
1183    return $input;
1184}
1185
1186{
1187
1188    title "Append & MultiStream Tests";
1189    # rt.24041
1190
1191    my $lex = LexFile->new( my $name );
1192    my $data1 = "the is the first";
1193    my $data2 = "and this is the second";
1194    my $trailing = "some trailing data";
1195
1196    my $fil;
1197
1198    title "One file";
1199    $fil = gzopen($name, "wb") ;
1200    ok $fil, "opened first file";
1201    is $fil->gzwrite($data1), length $data1, "write data1" ;
1202    ok ! $fil->gzclose(), "Closed";
1203
1204    is slurp($name), $data1, "got expected data from slurp";
1205    is trickle($name), $data1, "got expected data from trickle";
1206
1207    title "Two files";
1208    $fil = gzopen($name, "ab") ;
1209    ok $fil, "opened second file";
1210    is $fil->gzwrite($data2), length $data2, "write data2" ;
1211    ok ! $fil->gzclose(), "Closed";
1212
1213    is slurp($name), $data1 . $data2, "got expected data from slurp";
1214    is trickle($name), $data1 . $data2, "got expected data from trickle";
1215
1216    title "Trailing Data";
1217    open F, ">>$name";
1218    print F $trailing;
1219    close F;
1220
1221    is slurp($name), $data1 . $data2 . $trailing, "got expected data from slurp" ;
1222    is trickle($name), $data1 . $data2 . $trailing, "got expected data from trickle" ;
1223}
1224
1225{
1226    title "gzclose & gzflush return codes";
1227    # rt.29215
1228
1229    my $lex = LexFile->new( my $name );
1230    my $data1 = "the is some text";
1231    my $status;
1232
1233    $fil = gzopen($name, "wb") ;
1234    ok $fil, "opened first file";
1235    is $fil->gzwrite($data1), length $data1, "write data1" ;
1236    $status = $fil->gzflush(0xfff);
1237    ok   $status, "flush not ok" ;
1238    is $status, Z_STREAM_ERROR;
1239    ok ! $fil->gzflush(), "flush ok" ;
1240    ok ! $fil->gzclose(), "Closed";
1241}
1242
1243
1244
1245{
1246    title "repeated calls to flush - no compression";
1247
1248    my ($err, $x, $X, $status, $data);
1249
1250    ok( ($x, $err) = deflateInit ( ), "Create deflate object" );
1251    isa_ok $x, "Compress::Raw::Zlib::deflateStream" ;
1252    cmp_ok $err, '==', Z_OK, "status is Z_OK" ;
1253
1254
1255    ($data, $status) = $x->flush(Z_SYNC_FLUSH) ;
1256    cmp_ok  $status, '==', Z_OK, "flush returned Z_OK" ;
1257    ($data, $status) = $x->flush(Z_SYNC_FLUSH) ;
1258    cmp_ok  $status, '==', Z_OK, "second flush returned Z_OK" ;
1259    is $data, "", "no output from second flush";
1260}
1261
1262{
1263    title "repeated calls to flush - after compression";
1264
1265    my $hello = "I am a HAL 9000 computer" ;
1266    my ($err, $x, $X, $status, $data);
1267
1268    ok( ($x, $err) = deflateInit ( ), "Create deflate object" );
1269    isa_ok $x, "Compress::Raw::Zlib::deflateStream" ;
1270    cmp_ok $err, '==', Z_OK, "status is Z_OK" ;
1271
1272    ($data, $status) = $x->deflate($hello) ;
1273    cmp_ok $status, '==', Z_OK, "deflate returned Z_OK" ;
1274
1275    ($data, $status) = $x->flush(Z_SYNC_FLUSH) ;
1276    cmp_ok  $status, '==', Z_OK, "flush returned Z_OK" ;
1277    ($data, $status) = $x->flush(Z_SYNC_FLUSH) ;
1278    cmp_ok  $status, '==', Z_OK, "second flush returned Z_OK" ;
1279    is $data, "", "no output from second flush";
1280}
1281