]> icculus.org git repositories - icculus/xz.git/blob - tests/test_filter_flags.c
Fix test_filter_flags to match the new restriction of lc+lp.
[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 expected_ret)
55 {
56         memcrap(&decoded_flags, sizeof(decoded_flags));
57
58         size_t pos = 0;
59         if (lzma_filter_flags_decode(&decoded_flags, NULL,
60                                 buffer, &pos, known_size) != expected_ret
61                         || pos != known_size)
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_OK))
72                 return true;
73
74         if (known_flags.id != decoded_flags.id)
75                 return true;
76
77         return false;
78 }
79
80
81 #ifdef HAVE_FILTER_SUBBLOCK
82 static void
83 test_subblock(void)
84 {
85         // Test 1
86         known_flags.id = LZMA_FILTER_SUBBLOCK;
87         known_flags.options = NULL;
88
89         expect(!encode(2));
90         expect(!decode(2));
91         expect(decoded_flags.options != NULL);
92         expect(((lzma_options_subblock *)(decoded_flags.options))
93                         ->allow_subfilters);
94
95         // Test 2
96         known_flags.options = decoded_flags.options;
97         expect(!encode(2));
98         expect(!decode(2));
99         expect(decoded_flags.options != NULL);
100         expect(((lzma_options_subblock *)(decoded_flags.options))
101                         ->allow_subfilters);
102
103         free(decoded_flags.options);
104         free(known_flags.options);
105
106         // Test 3
107         buffer[0] = LZMA_FILTER_SUBBLOCK;
108         buffer[1] = 1;
109         buffer[2] = 0;
110         expect(!decode_ret(3, LZMA_HEADER_ERROR));
111 }
112 #endif
113
114
115 #ifdef HAVE_FILTER_SIMPLE
116 static void
117 test_simple(void)
118 {
119         // Test 1
120         known_flags.id = LZMA_FILTER_X86;
121         known_flags.options = NULL;
122
123         expect(!encode(2));
124         expect(!decode(2));
125         expect(decoded_flags.options == NULL);
126
127         // Test 2
128         lzma_options_simple options;
129         options.start_offset = 0;
130         known_flags.options = &options;
131         expect(!encode(2));
132         expect(!decode(2));
133         expect(decoded_flags.options == NULL);
134
135         // Test 3
136         options.start_offset = 123456;
137         known_flags.options = &options;
138         expect(!encode(6));
139         expect(!decode(6));
140         expect(decoded_flags.options != NULL);
141
142         lzma_options_simple *decoded = decoded_flags.options;
143         expect(decoded->start_offset == options.start_offset);
144
145         free(decoded);
146 }
147 #endif
148
149
150 #ifdef HAVE_FILTER_DELTA
151 static void
152 test_delta(void)
153 {
154         // Test 1
155         known_flags.id = LZMA_FILTER_DELTA;
156         known_flags.options = NULL;
157         expect(encode(99));
158
159         // Test 2
160         lzma_options_delta options = { 0 };
161         known_flags.options = &options;
162         expect(encode(99));
163
164         // Test 3
165         options.distance = LZMA_DELTA_DISTANCE_MIN;
166         expect(!encode(3));
167         expect(!decode(3));
168         expect(((lzma_options_delta *)(decoded_flags.options))
169                                 ->distance == options.distance);
170
171         free(decoded_flags.options);
172
173         // Test 4
174         options.distance = LZMA_DELTA_DISTANCE_MAX;
175         expect(!encode(3));
176         expect(!decode(3));
177         expect(((lzma_options_delta *)(decoded_flags.options))
178                                 ->distance == options.distance);
179
180         free(decoded_flags.options);
181
182         // Test 5
183         options.distance = LZMA_DELTA_DISTANCE_MAX + 1;
184         expect(encode(99));
185 }
186 #endif
187
188
189 #ifdef HAVE_FILTER_LZMA
190 static void
191 validate_lzma(void)
192 {
193         const lzma_options_lzma *known = known_flags.options;
194         const lzma_options_lzma *decoded = decoded_flags.options;
195
196         expect(known->dictionary_size <= decoded->dictionary_size);
197
198         if (known->dictionary_size == 1)
199                 expect(decoded->dictionary_size == 1);
200         else
201                 expect(known->dictionary_size + known->dictionary_size / 2
202                                 > decoded->dictionary_size);
203
204         expect(known->literal_context_bits == decoded->literal_context_bits);
205         expect(known->literal_pos_bits == decoded->literal_pos_bits);
206         expect(known->pos_bits == decoded->pos_bits);
207 }
208
209
210 static void
211 test_lzma(void)
212 {
213         // Test 1
214         known_flags.id = LZMA_FILTER_LZMA;
215         known_flags.options = NULL;
216         expect(encode(99));
217
218         // Test 2
219         lzma_options_lzma options = {
220                 .dictionary_size = 0,
221                 .literal_context_bits = 0,
222                 .literal_pos_bits = 0,
223                 .pos_bits = 0,
224                 .preset_dictionary = NULL,
225                 .preset_dictionary_size = 0,
226                 .mode = LZMA_MODE_INVALID,
227                 .fast_bytes = 0,
228                 .match_finder = LZMA_MF_INVALID,
229                 .match_finder_cycles = 0,
230         };
231
232         // Test 3 (empty dictionary not allowed)
233         known_flags.options = &options;
234         expect(encode(99));
235
236         // Test 4 (brute-force test some valid dictionary sizes)
237         options.dictionary_size = LZMA_DICTIONARY_SIZE_MIN;
238         while (options.dictionary_size != LZMA_DICTIONARY_SIZE_MAX) {
239                 if (++options.dictionary_size == 5000)
240                         options.dictionary_size = LZMA_DICTIONARY_SIZE_MAX - 5;
241
242                 expect(!encode(4));
243                 expect(!decode(4));
244                 validate_lzma();
245
246                 free(decoded_flags.options);
247         }
248
249         // Test 5 (too big dictionary size)
250         options.dictionary_size = LZMA_DICTIONARY_SIZE_MAX + 1;
251         expect(encode(99));
252
253         // Test 6 (brute-force test lc/lp/pb)
254         options.dictionary_size = LZMA_DICTIONARY_SIZE_MIN;
255         for (uint32_t lc = LZMA_LITERAL_CONTEXT_BITS_MIN;
256                         lc <= LZMA_LITERAL_CONTEXT_BITS_MAX; ++lc) {
257                 for (uint32_t lp = LZMA_LITERAL_POS_BITS_MIN;
258                                 lp <= LZMA_LITERAL_POS_BITS_MAX; ++lp) {
259                         for (uint32_t pb = LZMA_POS_BITS_MIN;
260                                         pb <= LZMA_POS_BITS_MAX; ++pb) {
261                                 if (lc + lp > LZMA_LITERAL_BITS_MAX)
262                                         continue;
263
264                                 options.literal_context_bits = lc;
265                                 options.literal_pos_bits = lp;
266                                 options.pos_bits = pb;
267
268                                 expect(!encode(4));
269                                 expect(!decode(4));
270                                 validate_lzma();
271
272                                 free(decoded_flags.options);
273                         }
274                 }
275         }
276 }
277 #endif
278
279
280 int
281 main(void)
282 {
283         lzma_init();
284
285 #ifdef HAVE_FILTER_SUBBLOCK
286         test_subblock();
287 #endif
288 #ifdef HAVE_FILTER_SIMPLE
289         test_simple();
290 #endif
291 #ifdef HAVE_FILTER_DELTA
292         test_delta();
293 #endif
294 #ifdef HAVE_FILTER_LZMA
295         test_lzma();
296 #endif
297
298         lzma_end(&strm);
299
300         return 0;
301 }