xref: /isa-l/igzip/igzip_inflate_test.c (revision 55fbfabfc60f1002bc8133b730a59f6abd22cfce)
1 /**********************************************************************
2   Copyright(c) 2011-2016 Intel Corporation All rights reserved.
3 
4   Redistribution and use in source and binary forms, with or without
5   modification, are permitted provided that the following conditions
6   are met:
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
12       distribution.
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.
16 
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 **********************************************************************/
29 
30 #define _FILE_OFFSET_BITS 64
31 #include <stdint.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <zlib.h>
35 #include "igzip_lib.h"
36 #include "huff_codes.h"
37 #include "test.h"
38 
39 /*Don't use file larger memory can support because compression and decompression
40  * are done in a stateless manner. */
41 #if __WORDSIZE == 64
42 #define MAX_INPUT_FILE_SIZE 2L * 1024L * 1024L * 1024L
43 #else
44 #define MAX_INPUT_FILE_SIZE 512L * 1024L * 1024L
45 #endif
46 
47 int
inflate_multi_pass(uint8_t * compress_buf,uint64_t compress_len,uint8_t * uncompress_buf,uint32_t * uncompress_len)48 inflate_multi_pass(uint8_t *compress_buf, uint64_t compress_len, uint8_t *uncompress_buf,
49                    uint32_t *uncompress_len)
50 {
51         struct inflate_state *state = NULL;
52         int ret = 0;
53         uint8_t *comp_tmp = NULL, *uncomp_tmp = NULL;
54         uint32_t comp_tmp_size = 0, uncomp_tmp_size = 0;
55         uint32_t comp_processed = 0, uncomp_processed = 0;
56 
57         state = malloc(sizeof(struct inflate_state));
58         if (state == NULL) {
59                 printf("Failed to allocate memory\n");
60                 exit(0);
61         }
62 
63         isal_inflate_init(state);
64 
65         state->next_in = NULL;
66         state->next_out = NULL;
67         state->avail_in = 0;
68         state->avail_out = 0;
69 
70         while (1) {
71                 if (state->avail_in == 0) {
72                         comp_tmp_size = rand() % (compress_len + 1);
73 
74                         if (comp_tmp_size >= compress_len - comp_processed)
75                                 comp_tmp_size = compress_len - comp_processed;
76 
77                         if (comp_tmp_size != 0) {
78                                 if (comp_tmp != NULL)
79                                         free(comp_tmp);
80 
81                                 comp_tmp = malloc(comp_tmp_size);
82 
83                                 if (comp_tmp == NULL) {
84                                         printf("Failed to allocate memory\n");
85                                         exit(0);
86                                 }
87 
88                                 memcpy(comp_tmp, compress_buf + comp_processed, comp_tmp_size);
89                                 comp_processed += comp_tmp_size;
90 
91                                 state->next_in = comp_tmp;
92                                 state->avail_in = comp_tmp_size;
93                         }
94                 }
95 
96                 if (state->avail_out == 0) {
97                         /* Save uncompressed data into uncompress_buf */
98                         if (uncomp_tmp != NULL) {
99                                 memcpy(uncompress_buf + uncomp_processed, uncomp_tmp,
100                                        uncomp_tmp_size);
101                                 uncomp_processed += uncomp_tmp_size;
102                         }
103 
104                         uncomp_tmp_size = rand() % (*uncompress_len + 1);
105 
106                         /* Limit size of buffer to be smaller than maximum */
107                         if (uncomp_tmp_size > *uncompress_len - uncomp_processed)
108                                 uncomp_tmp_size = *uncompress_len - uncomp_processed;
109 
110                         if (uncomp_tmp_size != 0) {
111 
112                                 if (uncomp_tmp != NULL) {
113                                         fflush(0);
114                                         free(uncomp_tmp);
115                                 }
116 
117                                 uncomp_tmp = malloc(uncomp_tmp_size);
118                                 if (uncomp_tmp == NULL) {
119                                         printf("Failed to allocate memory\n");
120                                         exit(0);
121                                 }
122 
123                                 state->avail_out = uncomp_tmp_size;
124                                 state->next_out = uncomp_tmp;
125                         }
126                 }
127 
128                 ret = isal_inflate(state);
129 
130                 if (state->block_state == ISAL_BLOCK_FINISH || ret != 0) {
131                         memcpy(uncompress_buf + uncomp_processed, uncomp_tmp, uncomp_tmp_size);
132                         *uncompress_len = state->total_out;
133                         break;
134                 }
135         }
136 
137         if (comp_tmp != NULL) {
138                 free(comp_tmp);
139                 comp_tmp = NULL;
140         }
141         if (uncomp_tmp != NULL) {
142                 free(uncomp_tmp);
143                 uncomp_tmp = NULL;
144         }
145 
146         free(state);
147         return ret;
148 }
149 
150 int
test(uint8_t * compressed_stream,uint64_t * compressed_length,uint8_t * uncompressed_stream,uint32_t uncompressed_length,uint8_t * uncompressed_test_stream,uint32_t uncompressed_test_stream_length)151 test(uint8_t *compressed_stream, uint64_t *compressed_length, uint8_t *uncompressed_stream,
152      uint32_t uncompressed_length, uint8_t *uncompressed_test_stream,
153      uint32_t uncompressed_test_stream_length)
154 {
155         int ret;
156         ret = compress2(compressed_stream, (uLongf *) compressed_length, uncompressed_stream,
157                         uncompressed_length, 6);
158         if (ret) {
159                 printf("Failed compressing input with exit code %d", ret);
160                 return ret;
161         }
162 
163         ret = inflate_multi_pass(compressed_stream + 2, *compressed_length - 2 - 4,
164                                  uncompressed_test_stream, &uncompressed_test_stream_length);
165         switch (ret) {
166         case 0:
167                 break;
168         case ISAL_END_INPUT:
169                 printf(" did not decompress all input\n");
170                 return ISAL_END_INPUT;
171                 break;
172         case ISAL_INVALID_BLOCK:
173                 printf("  invalid header\n");
174                 return ISAL_INVALID_BLOCK;
175                 break;
176         case ISAL_INVALID_SYMBOL:
177                 printf(" invalid symbol\n");
178                 return ISAL_INVALID_SYMBOL;
179                 break;
180         case ISAL_OUT_OVERFLOW:
181                 printf(" out buffer overflow\n");
182                 return ISAL_OUT_OVERFLOW;
183                 break;
184         case ISAL_INVALID_LOOKBACK:
185                 printf("Invalid lookback distance");
186                 return ISAL_INVALID_LOOKBACK;
187                 break;
188         default:
189                 printf(" error\n");
190                 return -1;
191                 break;
192         }
193 
194         if (uncompressed_test_stream_length != uncompressed_length) {
195                 printf("incorrect amount of data was decompressed from compressed data\n");
196                 printf("%d decompressed of %d compressed", uncompressed_test_stream_length,
197                        uncompressed_length);
198                 return -1;
199         }
200         if (memcmp(uncompressed_stream, uncompressed_test_stream, uncompressed_length)) {
201                 int i;
202                 for (i = 0; i < uncompressed_length; i++) {
203                         if (uncompressed_stream[i] != uncompressed_test_stream[i]) {
204                                 printf("first error at %d, 0x%x != 0x%x\n", i,
205                                        uncompressed_stream[i], uncompressed_test_stream[i]);
206                         }
207                 }
208                 printf(" decompressed data is not the same as the compressed data\n");
209                 return -1;
210         }
211 
212         return 0;
213 }
214 
215 int
main(int argc,char ** argv)216 main(int argc, char **argv)
217 {
218         int i, j, ret = 0, fin_ret = 0;
219         FILE *file = NULL;
220         uint64_t compressed_length, file_length;
221         uint64_t uncompressed_length, uncompressed_test_stream_length;
222         uint8_t *uncompressed_stream = NULL;
223         uint8_t *compressed_stream = NULL;
224         uint8_t *uncompressed_test_stream = NULL;
225 
226         if (argc == 1)
227                 printf("Error, no input file\n");
228         for (i = 1; i < argc; i++) {
229 
230                 file = NULL;
231                 uncompressed_stream = NULL;
232                 compressed_stream = NULL;
233                 uncompressed_test_stream = NULL;
234 
235                 file = fopen(argv[i], "r");
236                 if (file == NULL) {
237                         printf("Error opening file %s\n", argv[i]);
238                         return 1;
239                 } else
240                         printf("Starting file %s", argv[i]);
241                 fflush(0);
242                 file_length = get_filesize(file);
243                 if (file_length > MAX_INPUT_FILE_SIZE) {
244                         printf("\nFile too large to run on this test,"
245                                " Max 512MB for 32bit OS, 2GB for 64bit OS.\n");
246                         printf(" ... Fail\n");
247                         fclose(file);
248                         continue;
249                 }
250 
251                 compressed_length = compressBound(file_length);
252 
253                 if (file_length != 0) {
254                         uncompressed_stream = malloc(file_length);
255                         uncompressed_test_stream = malloc(file_length);
256                 }
257 
258                 compressed_stream = malloc(compressed_length);
259                 if (uncompressed_stream == NULL && file_length != 0) {
260                         printf("\nFailed to allocate input memory\n");
261                         exit(0);
262                 }
263 
264                 if (compressed_stream == NULL) {
265                         printf("\nFailed to allocate output memory\n");
266                         exit(0);
267                 }
268 
269                 if (uncompressed_test_stream == NULL && file_length != 0) {
270                         printf("\nFailed to allocate decompressed memory\n");
271                         exit(0);
272                 }
273 
274                 uncompressed_length = (uncompressed_stream == NULL)
275                                               ? 0
276                                               : fread(uncompressed_stream, 1, file_length, file);
277                 uncompressed_test_stream_length = uncompressed_length;
278                 ret = test(compressed_stream, &compressed_length, uncompressed_stream,
279                            uncompressed_length, uncompressed_test_stream,
280                            uncompressed_test_stream_length);
281                 if (ret) {
282                         for (j = 0; j < compressed_length; j++) {
283                                 if ((j & 31) == 0)
284                                         printf("\n");
285                                 else
286                                         printf(" ");
287                                 printf("0x%02x,", compressed_stream[j]);
288                         }
289                         printf("\n");
290                 }
291 
292                 fflush(0);
293                 fclose(file);
294                 if (compressed_stream != NULL)
295                         free(compressed_stream);
296                 if (uncompressed_stream != NULL)
297                         free(uncompressed_stream);
298                 if (uncompressed_test_stream != NULL)
299                         free(uncompressed_test_stream);
300                 if (ret) {
301                         printf(" ... Fail with exit code %d\n", ret);
302                         return ret;
303                 } else
304                         printf(" ... Pass\n");
305                 fin_ret |= ret;
306         }
307         return fin_ret;
308 }
309