]> icculus.org git repositories - icculus/xz.git/blob - tests/test_filter_flags.c
Imported to git.
[icculus/xz.git] / tests / test_filter_flags.c
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       test_filter_flags.c
4 /// \brief      Tests Filter Flags 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_options_filter known_flags;
25 static lzma_options_filter decoded_flags;
26 static lzma_stream strm = LZMA_STREAM_INIT;
27
28
29 static bool
30 encode(uint32_t known_size)
31 {
32         memcrap(buffer, sizeof(buffer));
33
34         uint32_t tmp;
35         if (lzma_filter_flags_size(&tmp, &known_flags) != LZMA_OK)
36                 return true;
37
38         if (tmp != known_size)
39                 return true;
40
41         size_t out_pos = 0;
42         if (lzma_filter_flags_encode(buffer, &out_pos, known_size,
43                         &known_flags) != LZMA_OK)
44                 return true;
45
46         if (out_pos != known_size)
47                 return true;
48
49         return false;
50 }
51
52
53 static bool
54 decode_ret(uint32_t known_size, lzma_ret ret_ok)
55 {
56         memcrap(&decoded_flags, sizeof(decoded_flags));
57
58         if (lzma_filter_flags_decoder(&strm, &decoded_flags) != LZMA_OK)
59                 return true;
60
61         if (decoder_loop_ret(&strm, buffer, known_size, ret_ok))
62                 return true;
63
64         return false;
65 }
66
67
68 static bool
69 decode(uint32_t known_size)
70 {
71         if (decode_ret(known_size, LZMA_STREAM_END))
72                 return true;
73
74         if (known_flags.id != decoded_flags.id)
75                 return true;
76
77         return false;
78 }
79
80
81 static void
82 test_copy(void)
83 {
84         // Test 1 (good)
85         known_flags.id = LZMA_FILTER_COPY;
86         known_flags.options = NULL;
87
88         expect(!encode(1));
89         expect(!decode(1));
90         expect(decoded_flags.options == NULL);
91
92         // Test 2 (invalid encoder options)
93         known_flags.options = &known_flags;
94         expect(encode(99));
95
96         // Test 3 (good but unusual Filter Flags field)
97         buffer[0] = 0xE0;
98         buffer[1] = LZMA_FILTER_COPY;
99         expect(!decode(2));
100         expect(decoded_flags.options == NULL);
101
102         // Test 4 (invalid Filter Flags field)
103         buffer[0] = 0xE1;
104         buffer[1] = LZMA_FILTER_COPY;
105         buffer[2] = 0;
106         expect(!decode_ret(3, LZMA_HEADER_ERROR));
107
108         // Test 5 (good but weird Filter Flags field)
109         buffer[0] = 0xFF;
110         buffer[1] = LZMA_FILTER_COPY;
111         buffer[2] = 0;
112         expect(!decode(3));
113         expect(decoded_flags.options == NULL);
114
115         // Test 6 (invalid Filter Flags field)
116         buffer[0] = 0xFF;
117         buffer[1] = LZMA_FILTER_COPY;
118         buffer[2] = 1;
119         buffer[3] = 0;
120         expect(!decode_ret(4, LZMA_HEADER_ERROR));
121 }
122
123
124 static void
125 test_subblock(void)
126 {
127         // Test 1
128         known_flags.id = LZMA_FILTER_SUBBLOCK;
129         known_flags.options = NULL;
130
131         expect(!encode(1));
132         expect(!decode(1));
133         expect(decoded_flags.options != NULL);
134         expect(((lzma_options_subblock *)(decoded_flags.options))
135                         ->allow_subfilters);
136
137         // Test 2
138         known_flags.options = decoded_flags.options;
139         expect(!encode(1));
140         expect(!decode(1));
141         expect(decoded_flags.options != NULL);
142         expect(((lzma_options_subblock *)(decoded_flags.options))
143                         ->allow_subfilters);
144
145         free(decoded_flags.options);
146         free(known_flags.options);
147
148         // Test 3
149         buffer[0] = 0xFF;
150         buffer[1] = LZMA_FILTER_SUBBLOCK;
151         buffer[2] = 1;
152         buffer[3] = 0;
153         expect(!decode_ret(4, LZMA_HEADER_ERROR));
154 }
155
156
157 static void
158 test_simple(void)
159 {
160         // Test 1
161         known_flags.id = LZMA_FILTER_X86;
162         known_flags.options = NULL;
163
164         expect(!encode(1));
165         expect(!decode(1));
166         expect(decoded_flags.options == NULL);
167
168         // Test 2
169         lzma_options_simple options;
170         options.start_offset = 0;
171         known_flags.options = &options;
172         expect(!encode(1));
173         expect(!decode(1));
174         expect(decoded_flags.options == NULL);
175
176         // Test 3
177         options.start_offset = 123456;
178         known_flags.options = &options;
179         expect(!encode(6));
180         expect(!decode(6));
181         expect(decoded_flags.options != NULL);
182
183         lzma_options_simple *decoded = decoded_flags.options;
184         expect(decoded->start_offset == options.start_offset);
185
186         free(decoded);
187 }
188
189
190 static void
191 test_delta(void)
192 {
193         // Test 1
194         known_flags.id = LZMA_FILTER_DELTA;
195         known_flags.options = NULL;
196         expect(encode(99));
197
198         // Test 2
199         lzma_options_delta options = { 0 };
200         known_flags.options = &options;
201         expect(encode(99));
202
203         // Test 3
204         options.distance = LZMA_DELTA_DISTANCE_MIN;
205         expect(!encode(2));
206         expect(!decode(2));
207         expect(((lzma_options_delta *)(decoded_flags.options))
208                                 ->distance == options.distance);
209
210         free(decoded_flags.options);
211
212         // Test 4
213         options.distance = LZMA_DELTA_DISTANCE_MAX;
214         expect(!encode(2));
215         expect(!decode(2));
216         expect(((lzma_options_delta *)(decoded_flags.options))
217                                 ->distance == options.distance);
218
219         free(decoded_flags.options);
220
221         // Test 5
222         options.distance = LZMA_DELTA_DISTANCE_MAX + 1;
223         expect(encode(99));
224 }
225
226
227 static void
228 validate_lzma(void)
229 {
230         const lzma_options_lzma *known = known_flags.options;
231         const lzma_options_lzma *decoded = decoded_flags.options;
232
233         expect(known->dictionary_size <= decoded->dictionary_size);
234
235         if (known->dictionary_size == 1)
236                 expect(decoded->dictionary_size == 1);
237         else
238                 expect(known->dictionary_size + known->dictionary_size / 2
239                                 > decoded->dictionary_size);
240
241         expect(known->literal_context_bits == decoded->literal_context_bits);
242         expect(known->literal_pos_bits == decoded->literal_pos_bits);
243         expect(known->pos_bits == decoded->pos_bits);
244 }
245
246
247 static void
248 test_lzma(void)
249 {
250         // Test 1
251         known_flags.id = LZMA_FILTER_LZMA;
252         known_flags.options = NULL;
253         expect(encode(99));
254
255         // Test 2
256         lzma_options_lzma options = {
257                 .dictionary_size = 0,
258                 .literal_context_bits = 0,
259                 .literal_pos_bits = 0,
260                 .pos_bits = 0,
261                 .preset_dictionary = NULL,
262                 .preset_dictionary_size = 0,
263                 .mode = LZMA_MODE_INVALID,
264                 .fast_bytes = 0,
265                 .match_finder = LZMA_MF_INVALID,
266                 .match_finder_cycles = 0,
267         };
268
269         // Test 3 (empty dictionary not allowed)
270         known_flags.options = &options;
271         expect(encode(99));
272
273         // Test 4 (brute-force test some valid dictionary sizes)
274         while (options.dictionary_size != LZMA_DICTIONARY_SIZE_MAX) {
275                 if (++options.dictionary_size == 5000)
276                         options.dictionary_size = LZMA_DICTIONARY_SIZE_MAX - 5;
277
278                 expect(!encode(3));
279                 expect(!decode(3));
280                 validate_lzma();
281
282                 free(decoded_flags.options);
283         }
284
285         // Test 5 (too big dictionary size)
286         options.dictionary_size = LZMA_DICTIONARY_SIZE_MAX + 1;
287         expect(encode(99));
288
289         // Test 6 (brute-force test lc/lp/pb)
290         options.dictionary_size = 1;
291         for (uint32_t lc = LZMA_LITERAL_CONTEXT_BITS_MIN;
292                         lc <= LZMA_LITERAL_CONTEXT_BITS_MAX; ++lc) {
293                 for (uint32_t lp = LZMA_LITERAL_POS_BITS_MIN;
294                                 lp <= LZMA_LITERAL_POS_BITS_MAX; ++lp) {
295                         for (uint32_t pb = LZMA_POS_BITS_MIN;
296                                         pb <= LZMA_POS_BITS_MAX; ++pb) {
297                                 options.literal_context_bits = lc;
298                                 options.literal_pos_bits = lp;
299                                 options.pos_bits = pb;
300
301                                 expect(!encode(3));
302                                 expect(!decode(3));
303                                 validate_lzma();
304
305                                 free(decoded_flags.options);
306                         }
307                 }
308         }
309 }
310
311
312 int
313 main()
314 {
315         lzma_init();
316
317         test_copy();
318         test_subblock();
319         test_simple();
320         test_delta();
321         test_lzma();
322
323         lzma_end(&strm);
324
325         return 0;
326 }