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