]> icculus.org git repositories - icculus/xz.git/blob - tests/test_block_header.c
* tests/test_block_header.c (test3): Remove duplicate initializer.
[icculus/xz.git] / tests / test_block_header.c
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       test_block_header.c
4 /// \brief      Tests Block Header coders
5 //
6 //  Copyright (C) 2007 Lasse Collin
7 //
8 //  This library is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU Lesser General Public
10 //  License as published by the Free Software Foundation; either
11 //  version 2.1 of the License, or (at your option) any later version.
12 //
13 //  This library is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 //  Lesser General Public License for more details.
17 //
18 ///////////////////////////////////////////////////////////////////////////////
19
20 #include "tests.h"
21
22
23 static uint8_t buffer[4096];
24 static lzma_stream strm = LZMA_STREAM_INIT;
25 static lzma_options_block known_options;
26 static lzma_options_block decoded_options;
27
28 // We want to test zero, one, and two filters in the chain.
29
30 static const lzma_options_filter filters_none[1] = {
31         {
32                 .id = LZMA_VLI_VALUE_UNKNOWN,
33                 .options = NULL,
34         },
35 };
36
37 static const lzma_options_filter filters_powerpc[2] = {
38         {
39                 .id = LZMA_FILTER_POWERPC,
40                 .options = NULL,
41         }, {
42                 .id = LZMA_VLI_VALUE_UNKNOWN,
43                 .options = NULL,
44         },
45 };
46
47 static const lzma_options_delta options_delta = {
48         .distance = 4,
49 };
50
51 static const lzma_options_filter filters_delta[3] = {
52         {
53                 .id = LZMA_FILTER_DELTA,
54                 .options = (void *)(&options_delta),
55         }, {
56                 .id = LZMA_FILTER_COPY,
57                 .options = NULL,
58         }, {
59                 .id = LZMA_VLI_VALUE_UNKNOWN,
60                 .options = NULL,
61         },
62 };
63
64
65 static bool
66 encode(uint32_t header_size)
67 {
68         memcrap(buffer, sizeof(buffer));
69
70         if (lzma_block_header_size(&known_options) != LZMA_OK)
71                 return true;
72
73         if (known_options.header_size != header_size)
74                 return true;
75
76         if (lzma_block_header_encode(buffer, &known_options) != LZMA_OK)
77                 return true;
78
79         return false;
80 }
81
82
83 static bool
84 decode_ret(uint32_t header_size, lzma_ret ret_ok)
85 {
86         memcrap(&decoded_options, sizeof(decoded_options));
87         decoded_options.has_crc32 = known_options.has_crc32;
88
89         expect(lzma_block_header_decoder(&strm, &decoded_options) == LZMA_OK);
90
91         return decoder_loop_ret(&strm, buffer, header_size, ret_ok);
92 }
93
94
95 static bool
96 decode(uint32_t header_size)
97 {
98         memcrap(&decoded_options, sizeof(decoded_options));
99         decoded_options.has_crc32 = known_options.has_crc32;
100
101         expect(lzma_block_header_decoder(&strm, &decoded_options) == LZMA_OK);
102
103         if (decoder_loop(&strm, buffer, header_size))
104                 return true;
105
106         if (known_options.has_eopm != decoded_options.has_eopm)
107                 return true;
108
109         if (known_options.is_metadata != decoded_options.is_metadata)
110                 return true;
111
112         if (known_options.compressed_size == LZMA_VLI_VALUE_UNKNOWN
113                         && known_options.compressed_reserve != 0) {
114                 if (decoded_options.compressed_size != 0)
115                         return true;
116         } else if (known_options.compressed_size
117                         != decoded_options.compressed_size) {
118                 return true;
119         }
120
121         if (known_options.uncompressed_size == LZMA_VLI_VALUE_UNKNOWN
122                         && known_options.uncompressed_reserve != 0) {
123                 if (decoded_options.uncompressed_size != 0)
124                         return true;
125         } else if (known_options.uncompressed_size
126                         != decoded_options.uncompressed_size) {
127                 return true;
128         }
129
130         if (known_options.compressed_reserve != 0
131                         && known_options.compressed_reserve
132                                 != decoded_options.compressed_reserve)
133                 return true;
134
135         if (known_options.uncompressed_reserve != 0
136                         && known_options.uncompressed_reserve
137                                 != decoded_options.uncompressed_reserve)
138                 return true;
139
140         if (known_options.padding != decoded_options.padding)
141                 return true;
142
143         return false;
144 }
145
146
147 static bool
148 code(uint32_t header_size)
149 {
150         return encode(header_size) || decode(header_size);
151 }
152
153
154 static bool
155 helper_loop(uint32_t unpadded_size, uint32_t multiple)
156 {
157         for (int i = 0; i <= LZMA_BLOCK_HEADER_PADDING_MAX; ++i) {
158                 known_options.padding = i;
159                 if (code(unpadded_size + i))
160                         return true;
161         }
162
163         for (int i = 0 - LZMA_BLOCK_HEADER_PADDING_MAX - 1;
164                         i <= LZMA_BLOCK_HEADER_PADDING_MAX + 1; ++i) {
165                 known_options.alignment = i;
166
167                 uint32_t size = unpadded_size;
168                 while ((size + known_options.alignment) % multiple)
169                         ++size;
170
171                 known_options.padding = LZMA_BLOCK_HEADER_PADDING_AUTO;
172                 if (code(size))
173                         return true;
174
175         } while (++known_options.alignment
176                         <= LZMA_BLOCK_HEADER_PADDING_MAX + 1);
177
178         return false;
179 }
180
181
182 static bool
183 helper(uint32_t unpadded_size, uint32_t multiple)
184 {
185         known_options.has_crc32 = false;
186         known_options.is_metadata = false;
187         if (helper_loop(unpadded_size, multiple))
188                 return true;
189
190         known_options.has_crc32 = false;
191         known_options.is_metadata = true;
192         if (helper_loop(unpadded_size, multiple))
193                 return true;
194
195         known_options.has_crc32 = true;
196         known_options.is_metadata = false;
197         if (helper_loop(unpadded_size + 4, multiple))
198                 return true;
199
200         known_options.has_crc32 = true;
201         known_options.is_metadata = true;
202         if (helper_loop(unpadded_size + 4, multiple))
203                 return true;
204
205         return false;
206 }
207
208
209 static void
210 test1(void)
211 {
212         known_options = (lzma_options_block){
213                 .has_eopm = true,
214                 .compressed_size = LZMA_VLI_VALUE_UNKNOWN,
215                 .uncompressed_size = LZMA_VLI_VALUE_UNKNOWN,
216                 .compressed_reserve = 0,
217                 .uncompressed_reserve = 0,
218         };
219         memcpy(known_options.filters, filters_none, sizeof(filters_none));
220         expect(!helper(2, 1));
221
222         memcpy(known_options.filters, filters_powerpc,
223                         sizeof(filters_powerpc));
224         expect(!helper(3, 4));
225
226         memcpy(known_options.filters, filters_delta, sizeof(filters_delta));
227         expect(!helper(5, 1));
228
229         known_options.padding = LZMA_BLOCK_HEADER_PADDING_MAX + 1;
230         expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR);
231 }
232
233
234 static void
235 test2_helper(uint32_t unpadded_size, uint32_t multiple)
236 {
237         known_options.has_eopm = true;
238         known_options.compressed_size = LZMA_VLI_VALUE_UNKNOWN;
239         known_options.uncompressed_size = LZMA_VLI_VALUE_UNKNOWN;
240         known_options.compressed_reserve = 1;
241         known_options.uncompressed_reserve = 1;
242         expect(!helper(unpadded_size + 2, multiple));
243
244         known_options.compressed_reserve = LZMA_VLI_BYTES_MAX;
245         known_options.uncompressed_reserve = LZMA_VLI_BYTES_MAX;
246         expect(!helper(unpadded_size + 18, multiple));
247
248         known_options.compressed_size = 1234;
249         known_options.uncompressed_size = 2345;
250         expect(!helper(unpadded_size + 18, multiple));
251
252         known_options.compressed_reserve = 1;
253         known_options.uncompressed_reserve = 1;
254         expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR);
255 }
256
257
258 static void
259 test2(void)
260 {
261         memcpy(known_options.filters, filters_none, sizeof(filters_none));
262         test2_helper(2, 1);
263
264         memcpy(known_options.filters, filters_powerpc,
265                         sizeof(filters_powerpc));
266         test2_helper(3, 4);
267
268         memcpy(known_options.filters, filters_delta,
269                         sizeof(filters_delta));
270         test2_helper(5, 1);
271 }
272
273
274 static void
275 test3(void)
276 {
277         known_options = (lzma_options_block){
278                 .has_crc32 = false,
279                 .has_eopm = true,
280                 .is_metadata = false,
281                 .compressed_size = LZMA_VLI_VALUE_UNKNOWN,
282                 .uncompressed_size = LZMA_VLI_VALUE_UNKNOWN,
283                 .compressed_reserve = 1,
284                 .uncompressed_reserve = 1,
285         };
286         memcpy(known_options.filters, filters_none, sizeof(filters_none));
287
288         known_options.header_size = 3;
289         expect(lzma_block_header_encode(buffer, &known_options)
290                         == LZMA_PROG_ERROR);
291
292         known_options.header_size = 4;
293         expect(lzma_block_header_encode(buffer, &known_options) == LZMA_OK);
294
295         known_options.header_size = 5;
296         expect(lzma_block_header_encode(buffer, &known_options)
297                         == LZMA_PROG_ERROR);
298
299         // NOTE: This assumes that Filter ID 0x1F is not supported. Update
300         // this test to use some other ID if 0x1F becomes supported.
301         known_options.filters[0].id = 0x1F;
302         known_options.header_size = 5;
303         expect(lzma_block_header_encode(buffer, &known_options)
304                         == LZMA_HEADER_ERROR);
305 }
306
307
308 static void
309 test4(void)
310 {
311         known_options = (lzma_options_block){
312                 .has_crc32 = false,
313                 .has_eopm = true,
314                 .is_metadata = false,
315                 .compressed_size = 0,
316                 .uncompressed_size = 0,
317                 .compressed_reserve = LZMA_VLI_BYTES_MAX,
318                 .uncompressed_reserve = LZMA_VLI_BYTES_MAX,
319                 .padding = 0,
320         };
321         memcpy(known_options.filters, filters_powerpc,
322                         sizeof(filters_powerpc));
323         expect(!code(21));
324
325         // Reserved bits
326         buffer[0] ^= 0x40;
327         expect(!decode_ret(1, LZMA_HEADER_ERROR));
328         buffer[0] ^= 0x40;
329
330         buffer[1] ^= 0x40;
331         expect(decode_ret(21, LZMA_HEADER_ERROR));
332         buffer[1] ^= 0x40;
333
334
335 }
336
337
338 int
339 main(void)
340 {
341         lzma_init();
342
343         test1();
344         test2();
345         test3();
346         test4();
347
348         lzma_end(&strm);
349
350         return 0;
351 }