1 /**********************************************************************
2 Copyright(c) 2011-2016 Intel Corporation All rights reserved.
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in
11 the documentation and/or other materials provided with the
13 * Neither the name of Intel Corporation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 **********************************************************************/
33 #include "igzip_lib.h"
34 #include "igzip_inflate_ref.h"
35 #include "crc_inflate.h"
42 # define TEST_SEED 0x1234
45 #define IBUF_SIZE (1024*1024)
47 #ifndef IGZIP_USE_GZIP_FORMAT
51 #define str1 "Short test string"
52 #define str2 "one two three four five six seven eight nine ten eleven twelve " \
53 "thirteen fourteen fifteen sixteen"
55 #define TYPE0_HDR_SIZE 5 /* Size of a type 0 blocks header in bytes */
56 #define TYPE0_MAX_SIZE 65535 /* Max length of a type 0 block in bytes (excludes the header) */
59 /* Defines for the possible error conditions */
60 enum IGZIP_TEST_ERROR_CODES
{
66 COMPRESS_INCORRECT_STATE
,
67 COMPRESS_INPUT_STREAM_INTEGRITY_ERROR
,
68 COMPRESS_OUTPUT_STREAM_INTEGRITY_ERROR
,
69 COMPRESS_END_OF_STREAM_NOT_SET
,
70 COMPRESS_ALL_INPUT_FAIL
,
71 COMPRESS_OUT_BUFFER_OVERFLOW
,
72 COMPRESS_LOOP_COUNT_OVERFLOW
,
73 COMPRESS_GENERAL_ERROR
,
76 INFLATE_INVALID_BLOCK_HEADER
,
77 INFLATE_INVALID_SYMBOL
,
78 INFLATE_OUT_BUFFER_OVERFLOW
,
79 INFLATE_INVALID_NON_COMPRESSED_BLOCK_LENGTH
,
80 INFLATE_LEFTOVER_INPUT
,
81 INFLATE_INCORRECT_OUTPUT_SIZE
,
82 INFLATE_INVALID_LOOK_BACK_DISTANCE
,
84 INCORRECT_GZIP_TRAILER
,
85 INFLATE_GENERAL_ERROR
,
93 const int hdr_bytes
= 300;
96 const uint8_t gzip_hdr
[10] = {
97 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
101 const uint32_t gzip_hdr_bytes
= 10;
102 const uint32_t gzip_trl_bytes
= 8;
104 const int trl_bytes
= 8;
105 const int gzip_extra_bytes
= 18;
108 const int trl_bytes
= 0;
109 const int gzip_extra_bytes
= 0;
113 #define HISTORY_SIZE 32*1024
117 /* Create random compressible data. This is achieved by randomly choosing a
118 * random character, or to repeat previous data in the stream for a random
119 * length and look back distance. The probability of a random character or a
120 * repeat being chosen is semi-randomly chosen by setting max_repeat_data to be
121 * differing values */
122 void create_rand_repeat_data(uint8_t * data
, int size
)
125 uint8_t *data_start
= data
;
126 uint32_t length
, distance
;
127 uint32_t max_repeat_data
= 256;
128 uint32_t power
= rand() % 32;
129 /* An array of the powers of 2 (except the final element which is 0) */
130 const uint32_t power_of_2_array
[] = {
131 0x00000001, 0x00000002, 0x00000004, 0x00000008,
132 0x00000010, 0x00000020, 0x00000040, 0x00000080,
133 0x00000100, 0x00000200, 0x00000400, 0x00000800,
134 0x00001000, 0x00002000, 0x00004000, 0x00008000,
135 0x00010000, 0x00020000, 0x00040000, 0x00080000,
136 0x00100000, 0x00200000, 0x00400000, 0x00800000,
137 0x01000000, 0x02000000, 0x04000000, 0x08000000,
138 0x10000000, 0x20000000, 0x40000000, 0x00000000
141 max_repeat_data
+= power_of_2_array
[power
];
147 next_data
= rand() % max_repeat_data
;
148 if (next_data
< 256) {
151 } else if (size
< 3) {
152 *data
++ = rand() % 256;
155 length
= (rand() % 256) + MIN_LENGTH
;
157 length
= (rand() % (size
- 2)) + MIN_LENGTH
;
159 distance
= (rand() % HISTORY_SIZE
) + MIN_DIST
;
160 if (distance
> data
- data_start
)
161 distance
= (rand() % (data
- data_start
)) + MIN_DIST
;
164 if (distance
<= length
) {
165 while (length
-- > 0) {
166 *data
= *(data
- distance
);
170 memcpy(data
, data
- distance
, length
);
175 void print_error(int error_code
)
177 switch (error_code
) {
181 printf("error: failed to allocate memory\n");
183 case FILE_READ_FAILED
:
184 printf("error: failed to read in file\n");
186 case COMPRESS_INCORRECT_STATE
:
187 printf("error: incorrect stream internal state\n");
189 case COMPRESS_INPUT_STREAM_INTEGRITY_ERROR
:
190 printf("error: inconsistent stream input buffer\n");
192 case COMPRESS_OUTPUT_STREAM_INTEGRITY_ERROR
:
193 printf("error: inconsistent stream output buffer\n");
195 case COMPRESS_END_OF_STREAM_NOT_SET
:
196 printf("error: end of stream not set\n");
198 case COMPRESS_ALL_INPUT_FAIL
:
199 printf("error: not all input data compressed\n");
201 case COMPRESS_OUT_BUFFER_OVERFLOW
:
202 printf("error: output buffer overflow while compressing data\n");
204 case COMPRESS_GENERAL_ERROR
:
205 printf("error: compression failed\n");
207 case INFLATE_END_OF_INPUT
:
208 printf("error: did not decompress all input\n");
210 case INFLATE_INVALID_BLOCK_HEADER
:
211 printf("error: invalid header\n");
213 case INFLATE_INVALID_SYMBOL
:
214 printf("error: invalid symbol found when decompressing input\n");
216 case INFLATE_OUT_BUFFER_OVERFLOW
:
217 printf("error: output buffer overflow while decompressing data\n");
219 case INFLATE_INVALID_NON_COMPRESSED_BLOCK_LENGTH
:
220 printf("error: invalid length bits in non-compressed block\n");
222 case INFLATE_GENERAL_ERROR
:
223 printf("error: decompression failed\n");
225 case INFLATE_LEFTOVER_INPUT
:
226 printf("error: the trailer of igzip output contains junk\n");
228 case INFLATE_INCORRECT_OUTPUT_SIZE
:
229 printf("error: incorrect amount of data was decompressed\n");
231 case INFLATE_INVALID_LOOK_BACK_DISTANCE
:
232 printf("error: invalid look back distance found while decompressing\n");
234 case INVALID_GZIP_HEADER
:
235 printf("error: incorrect gzip header found when inflating data\n");
237 case INCORRECT_GZIP_TRAILER
:
238 printf("error: incorrect gzip trailer found when inflating data\n");
240 case INVALID_FLUSH_ERROR
:
241 printf("error: invalid flush did not cause compression to error\n");
244 printf("error: decompressed data is not the same as the compressed data\n");
246 case OVERFLOW_TEST_ERROR
:
247 printf("error: overflow undetected\n");
250 printf("error: unknown error code\n");
254 void print_uint8_t(uint8_t * array
, uint64_t length
)
258 const int line_size
= 16;
259 printf("Length = %lu", length
);
260 for (i
= 0; i
< length
; i
++) {
261 if ((i
% line_size
) == 0)
262 printf("\n0x%08x\t", i
);
265 printf("0x%02x,", array
[i
]);
271 uint32_t check_gzip_header(uint8_t * z_buf
)
273 /* These values are defined in RFC 1952 page 4 */
274 const uint8_t ID1
= 0x1f, ID2
= 0x8b, CM
= 0x08, FLG
= 0;
277 /* Verify that the gzip header is the one used in hufftables_c.c */
278 for (i
= 0; i
< gzip_hdr_bytes
; i
++)
279 if (z_buf
[i
] != gzip_hdr
[i
])
280 ret
= INVALID_GZIP_HEADER
;
282 /* Verify that the gzip header is a valid gzip header */
284 ret
= INVALID_GZIP_HEADER
;
287 ret
= INVALID_GZIP_HEADER
;
289 /* Verfiy compression method is Deflate */
291 ret
= INVALID_GZIP_HEADER
;
293 /* The following comparison is specific to how gzip headers are written in igzip */
294 /* Verify no extra flags are set */
296 ret
= INVALID_GZIP_HEADER
;
298 /* The last 6 bytes in the gzip header do not contain any information
299 * important to decomrpessing the data */
304 uint32_t check_gzip_trl(struct inflate_state
* gstream
)
306 uint8_t *index
= NULL
;
307 uint32_t crc
, ret
= 0;
309 index
= gstream
->out_buffer
.next_out
- gstream
->out_buffer
.total_out
;
310 crc
= find_crc(index
, gstream
->out_buffer
.total_out
);
312 if (gstream
->out_buffer
.total_out
!= *(uint32_t *) (gstream
->in_buffer
.next_in
+ 4) ||
313 crc
!= *(uint32_t *) gstream
->in_buffer
.next_in
)
314 ret
= INCORRECT_GZIP_TRAILER
;
320 /* Inflate the compressed data and check that the decompressed data agrees with the input data */
321 int inflate_check(uint8_t * z_buf
, int z_size
, uint8_t * in_buf
, int in_size
)
323 /* Test inflate with reference inflate */
326 struct inflate_state gstream
;
327 uint32_t test_size
= in_size
;
328 uint8_t *test_buf
= NULL
;
331 assert(in_buf
!= NULL
);
334 test_buf
= malloc(test_size
);
336 if (test_buf
== NULL
)
337 return MALLOC_FAILED
;
339 if (test_buf
!= NULL
)
340 memset(test_buf
, 0xff, test_size
);
343 int gzip_hdr_result
, gzip_trl_result
;
345 gzip_hdr_result
= check_gzip_header(z_buf
);
346 z_buf
+= gzip_hdr_bytes
;
347 z_size
-= gzip_hdr_bytes
;
350 igzip_inflate_init(&gstream
, z_buf
, z_size
, test_buf
, test_size
);
351 ret
= igzip_inflate(&gstream
);
353 if (test_buf
!= NULL
)
354 mem_result
= memcmp(in_buf
, test_buf
, in_size
);
359 for (i
= 0; i
< in_size
; i
++) {
360 if (in_buf
[i
] != test_buf
[i
]) {
361 printf("First incorrect data at 0x%x of 0x%x, 0x%x != 0x%x\n",
362 i
, in_size
, in_buf
[i
], test_buf
[i
]);
369 gzip_trl_result
= check_gzip_trl(&gstream
);
370 gstream
.in_buffer
.avail_in
-= gzip_trl_bytes
;
371 gstream
.in_buffer
.next_in
+= gzip_trl_bytes
;
374 if (test_buf
!= NULL
)
381 return INFLATE_END_OF_INPUT
;
383 case INVALID_BLOCK_HEADER
:
384 return INFLATE_INVALID_BLOCK_HEADER
;
387 return INFLATE_INVALID_SYMBOL
;
389 case OUT_BUFFER_OVERFLOW
:
390 return INFLATE_OUT_BUFFER_OVERFLOW
;
392 case INVALID_NON_COMPRESSED_BLOCK_LENGTH
:
393 return INFLATE_INVALID_NON_COMPRESSED_BLOCK_LENGTH
;
395 case INVALID_LOOK_BACK_DISTANCE
:
396 return INFLATE_INVALID_LOOK_BACK_DISTANCE
;
399 return INFLATE_GENERAL_ERROR
;
403 if (gstream
.in_buffer
.avail_in
!= 0)
404 return INFLATE_LEFTOVER_INPUT
;
406 if (gstream
.out_buffer
.total_out
!= in_size
)
407 return INFLATE_INCORRECT_OUTPUT_SIZE
;
414 return INVALID_GZIP_HEADER
;
417 return INCORRECT_GZIP_TRAILER
;
423 /* Check if that the state of the data stream is consistent */
424 int stream_valid_check(struct isal_zstream
*stream
, uint8_t * in_buf
, uint32_t in_size
,
425 uint8_t * out_buf
, uint32_t out_size
, uint32_t in_processed
,
426 uint32_t out_processed
, uint32_t data_size
)
428 uint32_t total_in
, in_buffer_size
, total_out
, out_buffer_size
;
432 0) ? in_processed
: (in_processed
- in_size
) + (stream
->next_in
- in_buf
);
433 in_buffer_size
= (in_size
== 0) ? 0 : stream
->next_in
- in_buf
+ stream
->avail_in
;
435 /* Check for a consistent amount of data processed */
436 if (total_in
!= stream
->total_in
|| in_buffer_size
!= in_size
)
437 return COMPRESS_INPUT_STREAM_INTEGRITY_ERROR
;
440 (out_size
== 0) ? out_processed
: out_processed
+ (stream
->next_out
- out_buf
);
441 out_buffer_size
= (out_size
== 0) ? 0 : stream
->next_out
- out_buf
+ stream
->avail_out
;
443 /* Check for a consistent amount of data compressed */
444 if (total_out
!= stream
->total_out
|| out_buffer_size
!= out_size
) {
445 return COMPRESS_OUTPUT_STREAM_INTEGRITY_ERROR
;
451 /* Performs compression with checks to discover and verify the state of the
453 * stream: compress data structure which has been initialized to use
454 * in_buf and out_buf as the buffers
455 * data_size: size of all input data
456 * compressed_size: size of all available output buffers
457 * in_buf: next buffer of data to be compressed
458 * in_size: size of in_buf
459 * out_buf: next out put buffer where data is stored
460 * out_size: size of out_buf
461 * in_processed: the amount of input data which has been loaded into buffers
462 * to be compressed, this includes the data in in_buf
463 * out_processed: the amount of output data which has been compressed and stored,
464 * this does not include the data in the current out_buf
466 int isal_deflate_with_checks(struct isal_zstream
*stream
, uint32_t data_size
,
467 uint32_t compressed_size
, uint8_t * in_buf
, uint32_t in_size
,
468 uint32_t in_processed
, uint8_t * out_buf
, uint32_t out_size
,
469 uint32_t out_processed
)
471 int ret
, stream_check
;
472 struct isal_zstate
*state
= &stream
->internal_state
;
475 printf("Pre compression\n");
477 ("data_size = 0x%05x, in_processed = 0x%05x, in_size = 0x%05x, avail_in = 0x%05x, total_in = 0x%05x\n",
478 data_size
, in_processed
, in_size
, stream
->avail_in
, stream
->total_in
);
480 ("compressed_size = 0x%05x, out_processed = 0x%05x, out_size = 0x%05x, avail_out = 0x%05x, total_out = 0x%05x\n",
481 compressed_size
, out_processed
, out_size
, stream
->avail_out
, stream
->total_out
);
484 ret
= isal_deflate(stream
);
487 printf("Post compression\n");
489 ("data_size = 0x%05x, in_processed = 0x%05x, in_size = 0x%05x, avail_in = 0x%05x, total_in = 0x%05x\n",
490 data_size
, in_processed
, in_size
, stream
->avail_in
, stream
->total_in
);
492 ("compressed_size = 0x%05x, out_processed = 0x%05x, out_size = 0x%05x, avail_out = 0x%05x, total_out = 0x%05x\n",
493 compressed_size
, out_processed
, out_size
, stream
->avail_out
, stream
->total_out
);
497 /* Verify the stream is in a valid state */
498 stream_check
= stream_valid_check(stream
, in_buf
, in_size
, out_buf
, out_size
,
499 in_processed
, out_processed
, data_size
);
501 if (stream_check
!= 0)
504 if (ret
!= IGZIP_COMP_OK
)
505 return COMPRESS_GENERAL_ERROR
;
507 /* Check if the compression is completed */
508 if (state
->state
!= ZSTATE_END
)
509 if (compressed_size
- out_processed
- (out_size
- stream
->avail_out
) <= 0)
510 return COMPRESS_OUT_BUFFER_OVERFLOW
;
516 /* Compress the input data into the output buffer where the input buffer and
517 * output buffer are randomly segmented to test state information for the
519 int compress_multi_pass(uint8_t * data
, uint32_t data_size
, uint8_t * compressed_buf
,
520 uint32_t * compressed_size
, uint32_t flush_type
)
522 int ret
= IGZIP_COMP_OK
;
523 uint8_t *in_buf
= NULL
, *out_buf
= NULL
;
524 uint32_t in_size
= 0, out_size
= 0;
525 uint32_t in_processed
= 0, out_processed
= 0;
526 struct isal_zstream stream
;
527 struct isal_zstate
*state
= &stream
.internal_state
;
528 uint32_t loop_count
= 0;
531 printf("Starting Compress Multi Pass\n");
534 create_rand_repeat_data((uint8_t *) & stream
, sizeof(stream
));
536 isal_deflate_init(&stream
);
538 if (state
->state
!= ZSTATE_NEW_HDR
)
539 return COMPRESS_INCORRECT_STATE
;
541 stream
.flush
= flush_type
;
542 stream
.end_of_stream
= 0;
544 /* These are set here to allow the loop to run correctly */
546 stream
.avail_out
= 0;
551 /* Setup in buffer for next round of compression */
552 if (stream
.avail_in
== 0) {
553 if (flush_type
!= SYNC_FLUSH
|| state
->state
== ZSTATE_NEW_HDR
) {
554 /* Randomly choose size of the next out buffer */
555 in_size
= rand() % (data_size
+ 1);
557 /* Limit size of buffer to be smaller than maximum */
558 if (in_size
>= data_size
- in_processed
) {
559 in_size
= data_size
- in_processed
;
560 stream
.end_of_stream
= 1;
564 if (in_buf
!= NULL
) {
569 in_buf
= malloc(in_size
);
570 if (in_buf
== NULL
) {
574 memcpy(in_buf
, data
+ in_processed
, in_size
);
575 in_processed
+= in_size
;
577 stream
.avail_in
= in_size
;
578 stream
.next_in
= in_buf
;
583 /* Setup out buffer for next round of compression */
584 if (stream
.avail_out
== 0) {
585 /* Save compressed data inot compressed_buf */
586 if (out_buf
!= NULL
) {
587 memcpy(compressed_buf
+ out_processed
, out_buf
,
588 out_size
- stream
.avail_out
);
589 out_processed
+= out_size
- stream
.avail_out
;
592 /* Randomly choose size of the next out buffer */
593 out_size
= rand() % (*compressed_size
+ 1);
595 /* Limit size of buffer to be smaller than maximum */
596 if (out_size
> *compressed_size
- out_processed
)
597 out_size
= *compressed_size
- out_processed
;
600 if (out_buf
!= NULL
) {
605 out_buf
= malloc(out_size
);
606 if (out_buf
== NULL
) {
611 stream
.avail_out
= out_size
;
612 stream
.next_out
= out_buf
;
617 isal_deflate_with_checks(&stream
, data_size
, *compressed_size
, in_buf
,
618 in_size
, in_processed
, out_buf
, out_size
,
622 if (ret
== COMPRESS_OUT_BUFFER_OVERFLOW
623 || ret
== COMPRESS_INCORRECT_STATE
)
624 memcpy(compressed_buf
+ out_processed
, out_buf
, out_size
);
628 /* Check if the compression is completed */
629 if (state
->state
== ZSTATE_END
) {
630 memcpy(compressed_buf
+ out_processed
, out_buf
, out_size
);
631 *compressed_size
= stream
.total_out
;
642 if (ret
== COMPRESS_OUT_BUFFER_OVERFLOW
&& flush_type
== SYNC_FLUSH
643 && loop_count
>= MAX_LOOPS
)
644 ret
= COMPRESS_LOOP_COUNT_OVERFLOW
;
650 /* Compress the input data into the outbuffer in one call to isal_deflate */
651 int compress_single_pass(uint8_t * data
, uint32_t data_size
, uint8_t * compressed_buf
,
652 uint32_t * compressed_size
, uint32_t flush_type
)
654 int ret
= IGZIP_COMP_OK
;
655 struct isal_zstream stream
;
656 struct isal_zstate
*state
= &stream
.internal_state
;
659 printf("Starting Compress Single Pass\n");
662 create_rand_repeat_data((uint8_t *) & stream
, sizeof(stream
));
664 isal_deflate_init(&stream
);
666 if (state
->state
!= ZSTATE_NEW_HDR
)
667 return COMPRESS_INCORRECT_STATE
;
669 stream
.flush
= flush_type
;
670 stream
.avail_in
= data_size
;
671 stream
.next_in
= data
;
672 stream
.avail_out
= *compressed_size
;
673 stream
.next_out
= compressed_buf
;
674 stream
.end_of_stream
= 1;
677 isal_deflate_with_checks(&stream
, data_size
, *compressed_size
, data
, data_size
,
678 data_size
, compressed_buf
, *compressed_size
, 0);
680 /* Check if the compression is completed */
681 if (state
->state
== ZSTATE_END
)
682 *compressed_size
= stream
.total_out
;
683 else if (flush_type
== SYNC_FLUSH
&& stream
.avail_out
< 16)
684 ret
= COMPRESS_OUT_BUFFER_OVERFLOW
;
690 /* Statelessly compress the input buffer into the output buffer */
691 int compress_stateless(uint8_t * data
, uint32_t data_size
, uint8_t * compressed_buf
,
692 uint32_t * compressed_size
)
694 int ret
= IGZIP_COMP_OK
;
695 struct isal_zstream stream
;
697 create_rand_repeat_data((uint8_t *) & stream
, sizeof(stream
));
699 isal_deflate_init(&stream
);
701 stream
.avail_in
= data_size
;
702 stream
.end_of_stream
= 1;
703 stream
.next_in
= data
;
704 stream
.flush
= NO_FLUSH
;
706 stream
.avail_out
= *compressed_size
;
707 stream
.next_out
= compressed_buf
;
709 ret
= isal_deflate_stateless(&stream
);
711 /* verify the stream */
712 if (stream
.next_in
- data
!= stream
.total_in
||
713 stream
.total_in
+ stream
.avail_in
!= data_size
)
714 return COMPRESS_INPUT_STREAM_INTEGRITY_ERROR
;
716 if (stream
.next_out
- compressed_buf
!= stream
.total_out
||
717 stream
.total_out
+ stream
.avail_out
!= *compressed_size
)
718 return COMPRESS_OUTPUT_STREAM_INTEGRITY_ERROR
;
720 if (ret
!= IGZIP_COMP_OK
) {
721 if (ret
== STATELESS_OVERFLOW
)
722 return COMPRESS_OUT_BUFFER_OVERFLOW
;
724 return COMPRESS_GENERAL_ERROR
;
727 if (!stream
.end_of_stream
) {
728 return COMPRESS_END_OF_STREAM_NOT_SET
;
731 if (stream
.avail_in
!= 0)
732 return COMPRESS_ALL_INPUT_FAIL
;
734 *compressed_size
= stream
.total_out
;
740 /*Compress the input buffer into the output buffer, but switch the flush type in
741 * the middle of the compression to test what happens*/
742 int compress_swap_flush(uint8_t * data
, uint32_t data_size
, uint8_t * compressed_buf
,
743 uint32_t * compressed_size
, uint32_t flush_type
)
745 int ret
= IGZIP_COMP_OK
;
746 struct isal_zstream stream
;
747 struct isal_zstate
*state
= &stream
.internal_state
;
748 uint32_t partial_size
;
751 printf("Starting Compress Swap Flush\n");
754 isal_deflate_init(&stream
);
756 if (state
->state
!= ZSTATE_NEW_HDR
)
757 return COMPRESS_INCORRECT_STATE
;
759 partial_size
= rand() % (data_size
+ 1);
761 stream
.flush
= flush_type
;
762 stream
.avail_in
= partial_size
;
763 stream
.next_in
= data
;
764 stream
.avail_out
= *compressed_size
;
765 stream
.next_out
= compressed_buf
;
766 stream
.end_of_stream
= 0;
769 isal_deflate_with_checks(&stream
, data_size
, *compressed_size
, data
, partial_size
,
770 partial_size
, compressed_buf
, *compressed_size
, 0);
775 if (flush_type
== NO_FLUSH
)
776 flush_type
= SYNC_FLUSH
;
778 flush_type
= NO_FLUSH
;
780 stream
.flush
= flush_type
;
781 stream
.avail_in
= data_size
- partial_size
;
782 stream
.next_in
= data
+ partial_size
;
783 stream
.end_of_stream
= 1;
786 isal_deflate_with_checks(&stream
, data_size
, *compressed_size
, data
+ partial_size
,
787 data_size
- partial_size
, data_size
, compressed_buf
,
788 *compressed_size
, 0);
790 if (ret
== COMPRESS_GENERAL_ERROR
)
791 return INVALID_FLUSH_ERROR
;
793 *compressed_size
= stream
.total_out
;
798 /* Test isal_deflate_stateless */
799 int test_compress_stateless(uint8_t * in_buf
, uint32_t in_size
)
801 int ret
= IGZIP_COMP_OK
;
802 uint32_t z_size
, overflow
;
803 uint8_t *z_buf
= NULL
;
805 /* Test non-overflow case where a type 0 block is not written */
806 z_size
= 2 * in_size
+ hdr_bytes
+ trl_bytes
;
808 z_buf
= malloc(z_size
);
811 return MALLOC_FAILED
;
812 create_rand_repeat_data(z_buf
, z_size
);
814 ret
= compress_stateless(in_buf
, in_size
, z_buf
, &z_size
);
817 ret
= inflate_check(z_buf
, z_size
, in_buf
, in_size
);
826 /*Test non-overflow case where a type 0 block is possible to be written */
828 TYPE0_HDR_SIZE
* ((in_size
+ TYPE0_MAX_SIZE
- 1) / TYPE0_MAX_SIZE
) + in_size
+
831 if (z_size
== gzip_extra_bytes
)
832 z_size
+= TYPE0_HDR_SIZE
;
837 z_buf
= malloc(z_size
);
840 return MALLOC_FAILED
;
842 create_rand_repeat_data(z_buf
, z_size
);
844 ret
= compress_stateless(in_buf
, in_size
, z_buf
, &z_size
);
846 ret
= inflate_check(z_buf
, z_size
, in_buf
, in_size
);
849 printf("Compressed array: ");
850 print_uint8_t(z_buf
, z_size
);
853 print_uint8_t(in_buf
, in_size
);
861 /* Test random overflow case */
862 z_size
= rand() % z_size
;
864 if (z_size
> in_size
)
865 z_size
= rand() & in_size
;
868 z_buf
= malloc(z_size
);
871 return MALLOC_FAILED
;
874 overflow
= compress_stateless(in_buf
, in_size
, z_buf
, &z_size
);
876 if (overflow
!= COMPRESS_OUT_BUFFER_OVERFLOW
) {
878 printf("overflow error = %d\n", overflow
);
879 print_error(overflow
);
881 overflow
= inflate_check(z_buf
, z_size
, in_buf
, in_size
);
882 printf("inflate ret = %d\n", overflow
);
883 print_error(overflow
);
885 printf("Compressed array: ");
886 print_uint8_t(z_buf
, z_size
);
889 print_uint8_t(in_buf
, in_size
);
891 ret
= OVERFLOW_TEST_ERROR
;
903 /* Test isal_deflate */
904 int test_compress(uint8_t * in_buf
, uint32_t in_size
, uint32_t flush_type
)
906 int ret
= IGZIP_COMP_OK
, fin_ret
= IGZIP_COMP_OK
;
907 uint32_t overflow
= 0;
908 uint32_t z_size
, z_size_max
, z_compressed_size
;
909 uint8_t *z_buf
= NULL
;
911 /* Test a non overflow case */
912 if (flush_type
== NO_FLUSH
)
913 z_size_max
= 2 * in_size
+ hdr_bytes
+ trl_bytes
+ 2;
914 else if (flush_type
== SYNC_FLUSH
)
915 z_size_max
= 2 * in_size
+ MAX_LOOPS
* (hdr_bytes
+ trl_bytes
+ 5);
917 printf("Invalid Flush Parameter\n");
918 return COMPRESS_GENERAL_ERROR
;
923 z_buf
= malloc(z_size
);
925 print_error(MALLOC_FAILED
);
926 return MALLOC_FAILED
;
928 create_rand_repeat_data(z_buf
, z_size_max
);
930 ret
= compress_single_pass(in_buf
, in_size
, z_buf
, &z_size
, flush_type
);
933 ret
= inflate_check(z_buf
, z_size
, in_buf
, in_size
);
937 printf("Compressed array: ");
938 print_uint8_t(z_buf
, z_size
);
941 print_uint8_t(in_buf
, in_size
);
943 printf("Failed on compress single pass\n");
949 z_compressed_size
= z_size
;
951 create_rand_repeat_data(z_buf
, z_size_max
);
953 ret
= compress_multi_pass(in_buf
, in_size
, z_buf
, &z_size
, flush_type
);
956 ret
= inflate_check(z_buf
, z_size
, in_buf
, in_size
);
960 printf("Compressed array: ");
961 print_uint8_t(z_buf
, z_size
);
964 print_uint8_t(in_buf
, in_size
);
966 printf("Failed on compress multi pass\n");
974 /* Test random overflow case */
975 if (flush_type
== SYNC_FLUSH
&& z_compressed_size
> in_size
)
976 z_compressed_size
= in_size
+ 1;
978 z_size
= rand() % z_compressed_size
;
979 create_rand_repeat_data(z_buf
, z_size_max
);
981 overflow
= compress_single_pass(in_buf
, in_size
, z_buf
, &z_size
, flush_type
);
983 if (overflow
!= COMPRESS_OUT_BUFFER_OVERFLOW
) {
985 ret
= inflate_check(z_buf
, z_size
, in_buf
, in_size
);
987 /* Rarely single pass overflow will compresses data
988 * better than the initial run. This is to stop that
989 * case from erroring. */
990 if (overflow
!= 0 || ret
!= 0) {
992 printf("overflow error = %d\n", overflow
);
993 print_error(overflow
);
994 printf("inflate ret = %d\n", ret
);
995 print_error(overflow
);
997 printf("Compressed array: ");
998 print_uint8_t(z_buf
, z_size
);
1001 print_uint8_t(in_buf
, in_size
);
1003 printf("Failed on compress multi pass overflow\n");
1005 ret
= OVERFLOW_TEST_ERROR
;
1011 if (flush_type
== NO_FLUSH
) {
1012 create_rand_repeat_data(z_buf
, z_size_max
);
1014 overflow
= compress_multi_pass(in_buf
, in_size
, z_buf
, &z_size
, flush_type
);
1016 if (overflow
!= COMPRESS_OUT_BUFFER_OVERFLOW
) {
1018 ret
= inflate_check(z_buf
, z_size
, in_buf
, in_size
);
1020 /* Rarely multi pass overflow will compresses data
1021 * better than the initial run. This is to stop that
1022 * case from erroring */
1023 if (overflow
!= 0 || ret
!= 0) {
1025 printf("overflow error = %d\n", overflow
);
1026 print_error(overflow
);
1027 printf("inflate ret = %d\n", ret
);
1028 print_error(overflow
);
1030 printf("Compressed array: ");
1031 print_uint8_t(z_buf
, z_size
);
1034 print_uint8_t(in_buf
, in_size
);
1036 printf("Failed on compress multi pass overflow\n");
1038 ret
= OVERFLOW_TEST_ERROR
;
1049 /* Test swapping flush types in the middle of compression */
1050 int test_flush(uint8_t * in_buf
, uint32_t in_size
)
1052 int fin_ret
= IGZIP_COMP_OK
, ret
;
1053 uint32_t z_size
, flush_type
= 0;
1054 uint8_t *z_buf
= NULL
;
1056 z_size
= 2 * in_size
+ 2 * (hdr_bytes
+ trl_bytes
) + 8;
1058 z_buf
= malloc(z_size
);
1061 return MALLOC_FAILED
;
1063 create_rand_repeat_data(z_buf
, z_size
);
1065 while (flush_type
== NO_FLUSH
|| flush_type
== SYNC_FLUSH
)
1066 flush_type
= rand();
1068 /* Test invalid flush */
1069 ret
= compress_single_pass(in_buf
, in_size
, z_buf
, &z_size
, flush_type
);
1071 if (ret
== COMPRESS_GENERAL_ERROR
)
1074 printf("Failed when passing invalid flush parameter\n");
1075 ret
= INVALID_FLUSH_ERROR
;
1081 create_rand_repeat_data(z_buf
, z_size
);
1083 /* Test the valid case of SYNC_FLUSH followed by NO_FLUSH */
1084 ret
= compress_swap_flush(in_buf
, in_size
, z_buf
, &z_size
, rand() % 2);
1087 ret
= inflate_check(z_buf
, z_size
, in_buf
, in_size
);
1091 printf("Compressed array: ");
1092 print_uint8_t(z_buf
, z_size
);
1095 print_uint8_t(in_buf
, in_size
);
1097 printf("Failed on swapping from SYNC_FLUSH to NO_FLUSH\n");
1107 int get_filesize(FILE * f
)
1111 curr
= ftell(f
); /* Save current position */
1112 fseek(f
, 0L, SEEK_END
);
1114 fseek(f
, curr
, SEEK_SET
); /* Restore position */
1118 /* Run multiple compression tests on data stored in a file */
1119 int test_compress_file(char *file_name
)
1121 int ret
= IGZIP_COMP_OK
;
1123 uint8_t *in_buf
= NULL
;
1124 FILE *in_file
= NULL
;
1126 in_file
= fopen(file_name
, "rb");
1128 return FILE_READ_FAILED
;
1130 in_size
= get_filesize(in_file
);
1132 in_buf
= malloc(in_size
);
1134 return MALLOC_FAILED
;
1135 fread(in_buf
, 1, in_size
, in_file
);
1138 ret
|= test_compress_stateless(in_buf
, in_size
);
1139 ret
|= test_compress(in_buf
, in_size
, NO_FLUSH
);
1140 ret
|= test_compress(in_buf
, in_size
, SYNC_FLUSH
);
1141 ret
|= test_flush(in_buf
, in_size
);
1144 printf("Failed on file %s\n", file_name
);
1152 int main(int argc
, char *argv
[])
1154 int i
= 0, ret
= 0, fin_ret
= 0;
1155 uint32_t in_size
= 0, offset
= 0;
1159 setbuf(stdout
, NULL
);
1162 printf("Window Size: %d K\n", HIST_SIZE
);
1163 printf("Test Seed : %d\n", TEST_SEED
);
1164 printf("Randoms : %d\n", RANDOMS
);
1167 in_buf
= malloc(IBUF_SIZE
);
1168 if (in_buf
== NULL
) {
1169 fprintf(stderr
, "Can't allocate in_buf memory\n");
1174 printf("igzip_rand_test files: ");
1176 for (i
= 1; i
< argc
; i
++) {
1177 ret
|= test_compress_file(argv
[i
]);
1182 printf("................");
1183 printf("%s\n", ret
? "Fail" : "Pass");
1187 printf("igzip_rand_test stateless: ");
1189 ret
= test_compress_stateless((uint8_t *) str1
, sizeof(str1
));
1193 ret
|= test_compress_stateless((uint8_t *) str2
, sizeof(str2
));
1197 for (i
= 0; i
< RANDOMS
; i
++) {
1198 in_size
= rand() % (IBUF_SIZE
+ 1);
1199 offset
= rand() % (IBUF_SIZE
+ 1 - in_size
);
1202 create_rand_repeat_data(in_buf
, in_size
);
1204 ret
|= test_compress_stateless(in_buf
, in_size
);
1208 if (i
% (RANDOMS
/ 16) == 0)
1217 printf("%s\n", ret
? "Fail" : "Pass");
1219 printf("igzip_rand_test NO_FLUSH: ");
1221 ret
= test_compress((uint8_t *) str1
, sizeof(str1
), NO_FLUSH
);
1225 ret
|= test_compress((uint8_t *) str2
, sizeof(str2
), NO_FLUSH
);
1229 for (i
= 0; i
< RANDOMS
; i
++) {
1230 in_size
= rand() % (IBUF_SIZE
+ 1);
1231 offset
= rand() % (IBUF_SIZE
+ 1 - in_size
);
1234 create_rand_repeat_data(in_buf
, in_size
);
1236 ret
|= test_compress(in_buf
, in_size
, NO_FLUSH
);
1240 if (i
% (RANDOMS
/ 16) == 0)
1248 printf("%s\n", ret
? "Fail" : "Pass");
1250 printf("igzip_rand_test SYNC_FLUSH: ");
1252 ret
= test_compress((uint8_t *) str1
, sizeof(str1
), SYNC_FLUSH
);
1256 ret
|= test_compress((uint8_t *) str2
, sizeof(str2
), SYNC_FLUSH
);
1260 for (i
= 0; i
< RANDOMS
; i
++) {
1261 in_size
= rand() % (IBUF_SIZE
+ 1);
1262 offset
= rand() % (IBUF_SIZE
+ 1 - in_size
);
1265 create_rand_repeat_data(in_buf
, in_size
);
1267 ret
|= test_compress(in_buf
, in_size
, SYNC_FLUSH
);
1271 if (i
% (RANDOMS
/ 16) == 0)
1279 printf("%s\n", ret
? "Fail" : "Pass");
1281 printf("igzip rand test finished: %s\n",
1282 fin_ret
? "Some tests failed" : "All tests passed");
1284 return fin_ret
!= IGZIP_COMP_OK
;